# -*- coding: utf-8 -*-
import math

import numpy as np
np.pi = 3.14159
from PySide2.QtCore import Qt, QEvent, QPoint
from PySide2.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QTableWidget, QProgressDialog, QItemDelegate, \
    QComboBox, QHeaderView, QFrame, QToolTip, QHBoxLayout, QPushButton
from functools import partial

from src.form.form_main import Ui_MainWindow
from src.utils import *
from src.algorithm import AnchorDesign, Product
import pandas as pd


class MainController(QMainWindow, Ui_MainWindow):
    def __init__(self, parent):
        super(MainController, self).__init__()
        self.copy_obj = None
        self.original_pixmap = None
        self.parent = parent
        self.folder_path = self.parent.folder_path
        self.setupUi(self)
        self.statusbar.hide()
        set_window_size_by_resolution(self)
        # 初始化需要隐藏的表格
        init_hide_tables = [self.tableWidget_laya_kuoda_base_youhua, self.tableWidget_laya_kuoda_cal_maogu_square,
                            self.tableWidget_laya_kuoda_cal_maozuo_square,
                            self.tableWidget_laya_dengzhi_base_youhua, self.tableWidget_laya_dengzhi_cal_maogu1_square,
                            self.tableWidget_laya_dengzhi_cal_maozuo1_square,
                            self.tableWidget_yalikuoda_base_youhua, self.tableWidget_yalikuoda_cal_maogu_square,
                            self.tableWidget_yalikuoda_cal_maozuo_square,
                            self.tableWidget_yalidengzhi_base_youhua, self.tableWidget_yalidengzhi_cal_maogu_square,
                            self.tableWidget_yalidengzhi_cal_maozuo_square, ]
        for tb in init_hide_tables:
            tb.hide()
        init_combo_guifan = [self.comboBox_layakuodaa_base_guifan, self.comboBox_layadengzhi_guifan_info,
                             self.comboBox_yalidengzhi_guifan_info, self.comboBox_yalidengzhi_guifan]
        for cb in init_combo_guifan:
            cb.addItems(['《精轧螺纹钢筋预应力抗浮锚杆技术规程》（T/CECS 1706—2024）', '其他技术规范'])
        # 优化方法/传统方法下拉框
        combo_method = [
            {"combobox": self.comboBox_laya_kuoda_cal_method, "传统方法": self.tableWidget_laya_kuoda_base,
             "优化方法": self.tableWidget_laya_kuoda_base_youhua},
            {"combobox": self.comboBox_laya_dengzhi_cal_method, "传统方法": self.tableWidget_laya_dengzhi_base,
             "优化方法": self.tableWidget_laya_dengzhi_base_youhua},
            {"combobox": self.comboBox_yalikuoda_cal_method, "传统方法": self.tableWidget_yalikuoda_base,
             "优化方法": self.tableWidget_yalikuoda_base_youhua},
            {"combobox": self.comboBox_yalidengzhi_cal_method, "传统方法": self.tableWidget_yalidengzhi_base,
             "优化方法": self.tableWidget_yalidengzhi_base_youhua},
        ]
        for item in combo_method:
            combobox = item['combobox']
            combobox.addItems(['传统方法', '优化方法'])
            combobox.currentTextChanged.connect(
                partial(self.onComboBoxChanged, combobox, combobox.currentText(), item['传统方法'], item['优化方法']))
        # 圆形锚固板/正方形锚固板下拉框
        var = [
            {"combobox": self.comboBox_laya_kuoda_cal_all_maogu, "圆形锚固板": self.tableWidget_laya_kuoda_cal_maogu,
             "正方形锚固板": self.tableWidget_laya_kuoda_cal_maogu_square,
             'combobox_child': self.comboBox_laya_kuoda_cal_all_maozuo,'combobox_child_label':self.label_6},
            {"combobox": self.comboBox_laya_kuoda_cal_all_maozuo, "圆形锚固板": self.tableWidget_laya_kuoda_cal_maozuo,
             "正方形锚固板": self.tableWidget_laya_kuoda_cal_maozuo_square},

            {"combobox": self.comboBox_laya_dengzhi_cal_all_maogu,"圆形锚固板": self.tableWidget_laya_dengzhi_cal_maogu1,
             "正方形锚固板": self.tableWidget_laya_dengzhi_cal_maogu1_square,
             'combobox_child': self.comboBox_laya_dengzhi_cal_all_maozuo,'combobox_child_label':self.label_8},
            {"combobox": self.comboBox_laya_dengzhi_cal_all_maozuo,"圆形锚固板": self.tableWidget_laya_dengzhi_cal_maozuo1,
             "正方形锚固板": self.tableWidget_laya_dengzhi_cal_maozuo1_square},

            {"combobox": self.comboBox_yalikuoda_cal_all_maogu, "圆形锚固板": self.tableWidget_yalikuoda_cal_maogu,
             "正方形锚固板": self.tableWidget_yalikuoda_cal_maogu_square,
             'combobox_child': self.comboBox_yalikuodai_cal_all_maozuo,'combobox_child_label':self.label_15},
            {"combobox": self.comboBox_yalikuodai_cal_all_maozuo, "圆形锚固板": self.tableWidget_yalikuoda_cal_maozuo,
             "正方形锚固板": self.tableWidget_yalikuoda_cal_maozuo_square},

            {"combobox": self.comboBox_yalidengzhi_cal_all_maogu, "圆形锚固板": self.tableWidget_yalidengzhi_cal_maogu,
             "正方形锚固板": self.tableWidget_yalidengzhi_cal_maogu_square,
             'combobox_child': self.comboBox_yalidengzhi_cal_all_maozuo,'combobox_child_label':self.label_18},
            {"combobox": self.comboBox_yalidengzhi_cal_all_maozuo,"圆形锚固板": self.tableWidget_yalidengzhi_cal_maozuo,
             "正方形锚固板": self.tableWidget_yalidengzhi_cal_maozuo_square},
        ]
        for item in var:
            combobox = item['combobox']
            combobox.addItems(['圆形锚固板', '正方形锚固板'])
            combobox.currentTextChanged.connect(
                partial(self.onComboBoxChanged1, combobox, combobox.currentText(), item['圆形锚固板'],
                        item['正方形锚固板'], item.get('combobox_child', None)))
            if item.get('combobox_child', None):
                item['combobox_child'].hide()
                item['combobox_child_label'].hide()
        # 验算表格同步按钮
        self.calc_rules = [
            # 拉压扩大-圆形
            # nd
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu, 1, 0),'rule_id': 'nd','calculator': partial(self.set_child_tb_value_nd,
                    source1=(self.tableWidget_laya_kuoda_cal_maogu, 1, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_maozuo, 0, 0),(self.tableWidget_laya_kuoda_cal_shouyacz_2, 0, 0)]
                )
            },
            # R
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu, 2, 0),'rule_id': 'R_div100','calculator': partial(self.set_child_tb_value_R,
                    source1=(self.tableWidget_laya_kuoda_cal_maogu, 2, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),]
                )
            },
            # Abt
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),'rule_id': 'Abt_R','calculator': partial(self.set_child_tb_value_Abt,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    source2=(self.tableWidget_laya_kuoda_cal_maozuo, 2, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_maozuo, 4, 0),]
                )
            },
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo, 2, 0),'rule_id': 'Abt_h0','calculator': partial(self.set_child_tb_value_Abt,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    source2=(self.tableWidget_laya_kuoda_cal_maozuo, 2, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_maozuo, 4, 0),]
                )
            },
            # Ab
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),'rule_id': 'Ab',
                'calculator': partial(self.set_child_tb_value_Ab,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 1, 0),]
                )
            },
            # A1
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),'rule_id': 'A1','calculator': partial(self.set_child_tb_value_A1,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 2, 0),]
                )
            },
            # Aln
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu, 2, 0),'rule_id': 'Aln_R','calculator': partial(self.set_child_tb_value_Aln,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    source2=(self.tableWidget_laya_kuoda_cal_maogu, 5, 0),
                    source3=(self.tableWidget_laya_kuoda_cal_maogu, 6, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 4, 0),]
                )
            },
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu, 5, 0),'rule_id': 'Aln_d','calculator': partial(self.set_child_tb_value_Aln,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    source2=(self.tableWidget_laya_kuoda_cal_maogu, 5, 0),
                    source3=(self.tableWidget_laya_kuoda_cal_maogu, 6, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 4, 0),]
                )
            },
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu, 6, 0),'rule_id': 'Aln_hn','calculator': partial(self.set_child_tb_value_Aln,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    source2=(self.tableWidget_laya_kuoda_cal_maogu, 5, 0),
                    source3=(self.tableWidget_laya_kuoda_cal_maogu, 6, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 4, 0),]
                )
            },
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),'rule_id': 'Aln_R_div1000','calculator': partial(self.set_child_tb_value_Aln,
                    source1=(self.tableWidget_laya_kuoda_cal_maozuo, 1, 0),
                    source2=(self.tableWidget_laya_kuoda_cal_maogu, 5, 0),
                    source3=(self.tableWidget_laya_kuoda_cal_maogu, 6, 0),
                    targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 4, 0),]
                )
            },
            # tuk_user_d
            {
              'trigger':(self.tableWidget_laya_kuoda_design_user_choice,1,0),'rule_id': 'layakuoda_final_tuk_d','calculator': partial(self.use_get_final_user_tuk,
                class_type=(0),
                d=(self.tableWidget_laya_kuoda_design_user_choice, 1, 0),
                D1=(self.tableWidget_laya_kuoda_design_user_choice, 2, 0),
                h=(self.tableWidget_laya_kuoda_design_user_choice, 3, 0),
                D2=(self.tableWidget_laya_kuoda_design_user_choice, 4, 0),
                LD=(self.tableWidget_laya_kuoda_design_user_choice, 5, 0),
                targets=[(self.tableWidget_laya_kuoda_design_user_choice, 6, 0),]
              )

            },
            {
                'trigger': (self.tableWidget_laya_kuoda_design_user_choice, 2, 0), 'rule_id': 'layakuoda_final_tuk_D1',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(0),
                                      d=(self.tableWidget_laya_kuoda_design_user_choice, 1, 0),
                                      D1=(self.tableWidget_laya_kuoda_design_user_choice, 2, 0),
                                      h=(self.tableWidget_laya_kuoda_design_user_choice, 3, 0),
                                      D2=(self.tableWidget_laya_kuoda_design_user_choice, 4, 0),
                                      LD=(self.tableWidget_laya_kuoda_design_user_choice, 5, 0),
                                      targets=[(self.tableWidget_laya_kuoda_design_user_choice, 6, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_laya_kuoda_design_user_choice, 3, 0), 'rule_id': 'layakuoda_final_tuk_h',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(0),
                                      d=(self.tableWidget_laya_kuoda_design_user_choice, 1, 0),
                                      D1=(self.tableWidget_laya_kuoda_design_user_choice, 2, 0),
                                      h=(self.tableWidget_laya_kuoda_design_user_choice, 3, 0),
                                      D2=(self.tableWidget_laya_kuoda_design_user_choice, 4, 0),
                                      LD=(self.tableWidget_laya_kuoda_design_user_choice, 5, 0),
                                      targets=[(self.tableWidget_laya_kuoda_design_user_choice, 6, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_laya_kuoda_design_user_choice, 4, 0), 'rule_id': 'layakuoda_final_tuk_D2',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(0),
                                      d=(self.tableWidget_laya_kuoda_design_user_choice, 1, 0),
                                      D1=(self.tableWidget_laya_kuoda_design_user_choice, 2, 0),
                                      h=(self.tableWidget_laya_kuoda_design_user_choice, 3, 0),
                                      D2=(self.tableWidget_laya_kuoda_design_user_choice, 4, 0),
                                      LD=(self.tableWidget_laya_kuoda_design_user_choice, 5, 0),
                                      targets=[(self.tableWidget_laya_kuoda_design_user_choice, 6, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_laya_kuoda_design_user_choice, 5, 0), 'rule_id': 'layakuoda_final_tuk_LD',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(0),
                                      d=(self.tableWidget_laya_kuoda_design_user_choice, 1, 0),
                                      D1=(self.tableWidget_laya_kuoda_design_user_choice, 2, 0),
                                      h=(self.tableWidget_laya_kuoda_design_user_choice, 3, 0),
                                      D2=(self.tableWidget_laya_kuoda_design_user_choice, 4, 0),
                                      LD=(self.tableWidget_laya_kuoda_design_user_choice, 5, 0),
                                      targets=[(self.tableWidget_laya_kuoda_design_user_choice, 6, 0), ]
                                      )

            },
            # 方形
            # nd
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu_square, 3, 0), 'rule_id': 'layakuoda_sq_nd',
                'calculator': partial(self.set_child_tb_value_nd,
                                      source1=(self.tableWidget_laya_kuoda_cal_maogu_square, 3, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_maozuo_square, 0, 0),(self.tableWidget_laya_kuoda_cal_shouyacz_2, 0, 0)])
            },
            # a
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu_square, 5, 0), 'rule_id': 'layakuoda_sq_a',
                'calculator': partial(self.set_child_tb_value_R,
                                      source1=(self.tableWidget_laya_kuoda_cal_maogu_square, 5, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0)])
            },
            # Abt
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0), 'rule_id': 'layakuoda_sq_Abt_a',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_laya_kuoda_cal_maozuo_square, 2, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_maozuo_square, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo_square, 2, 0), 'rule_id': 'layakuoda_sq_Abt_h0',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_laya_kuoda_cal_maozuo_square, 2, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_maozuo_square, 4, 0)])
            },
            # Ab
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0), 'rule_id': 'layakuoda_sq_Ab',
                'calculator': partial(self.set_child_tb_value_sq_Ab,
                                      source1=(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 1, 0)])
            },
            # A1
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0), 'rule_id': 'layakuoda_sq_A1',
                'calculator': partial(self.set_child_tb_value_sq_A1,
                                      source1=(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 2, 0)])
            },
            # Aln
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0), 'rule_id': 'layakuoda_sq_Aln_a',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_laya_kuoda_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_laya_kuoda_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu_square, 6, 0), 'rule_id': 'layakuoda_sq_Aln_d',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_laya_kuoda_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_laya_kuoda_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_laya_kuoda_cal_maogu_square, 4, 0), 'rule_id': 'layakuoda_sq_Aln_hn',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_laya_kuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_laya_kuoda_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_laya_kuoda_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_laya_kuoda_cal_shouyacz_2, 4, 0)])
            },
            # 锚杆数
            {
                'trigger': (self.tableWidget_laya_kuoda_design, 0, 0), 'rule_id': 'layakuoda_maogan_count',
                'calculator': partial(self.set_maogan_count,
                                      source1=(self.tableWidget_laya_kuoda_design, 0, 0),
                                      targets=[(self.tableWidget_laya_kuoda_design_user_choice, 0, 0)])
            },

            # 拉压等直
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1, 1, 0), 'rule_id': 'layadengzhi_nd',
                'calculator': partial(self.set_child_tb_value_nd,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maogu1, 1, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1, 0, 0),
                                               (self.tableWidget_laya_dengzhi_cal_shouyacz, 0, 0)]
                                      )
            },
            # R
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1, 2, 0), 'rule_id': 'layadengzhi_R_div100',
                'calculator': partial(self.set_child_tb_value_R,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maogu1, 2, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0), ]
                                      )
            },
            # Abt
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0), 'rule_id': 'layadengzhi_Abt_R',
                'calculator': partial(self.set_child_tb_value_Abt,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maozuo1, 2, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1, 2, 0), 'rule_id': 'layadengzhi_Abt_h0',
                'calculator': partial(self.set_child_tb_value_Abt,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maozuo1, 2, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1, 4, 0), ]
                                      )
            },
            # Ab
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0), 'rule_id': 'layadengzhi_Ab',
                'calculator': partial(self.set_child_tb_value_Ab,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 1, 0), ]
                                      )
            },
            # A1
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0), 'rule_id': 'layadengzhi_A1',
                'calculator': partial(self.set_child_tb_value_A1,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 2, 0), ]
                                      )
            },
            # Aln
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1, 2, 0), 'rule_id': 'layadengzhi_Aln_R',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maogu1, 5, 0),
                                      source3=(self.tableWidget_laya_dengzhi_cal_maogu1, 6, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1, 5, 0), 'rule_id': 'layadengzhi_Aln_d',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maogu1, 5, 0),
                                      source3=(self.tableWidget_laya_dengzhi_cal_maogu1, 6, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1, 6, 0), 'rule_id': 'layadengzhi_Aln_hn',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maogu1, 5, 0),
                                      source3=(self.tableWidget_laya_dengzhi_cal_maogu1, 6, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0), 'rule_id': 'layadengzhi_Aln_R_div1000',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maogu1, 5, 0),
                                      source3=(self.tableWidget_laya_dengzhi_cal_maogu1, 6, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_design_user, 1, 0), 'rule_id': 'layadengzhi_final_tuk_d',
                'calculator': partial(self.use_get_final_user_tuk_layadedngzhi,
                                      class_type=(1),
                                      d=(self.tableWidget_laya_dengzhi_design_user, 1, 0),
                                      D1=(self.tableWidget_laya_dengzhi_design_user, 2, 0),
                                      ziyou=(self.tableWidget_laya_dengzhi_design_user, 3, 0),
                                      nianjie=(self.tableWidget_laya_dengzhi_design_user, 4, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_design_user, 5, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_design_user, 2, 0), 'rule_id': 'layadengzhi_final_tuk_D',
                'calculator': partial(self.use_get_final_user_tuk_layadedngzhi,
                                      class_type=(1),
                                      d=(self.tableWidget_laya_dengzhi_design_user, 1, 0),
                                      D1=(self.tableWidget_laya_dengzhi_design_user, 2, 0),
                                      ziyou=(self.tableWidget_laya_dengzhi_design_user, 3, 0),
                                      nianjie=(self.tableWidget_laya_dengzhi_design_user, 4, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_design_user, 5, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_design_user, 3, 0), 'rule_id': 'layadengzhi_final_tuk_ziyou',
                'calculator': partial(self.use_get_final_user_tuk_layadedngzhi,
                                      class_type=(1),
                                      d=(self.tableWidget_laya_dengzhi_design_user, 1, 0),
                                      D1=(self.tableWidget_laya_dengzhi_design_user, 2, 0),
                                      ziyou=(self.tableWidget_laya_dengzhi_design_user, 3, 0),
                                      nianjie=(self.tableWidget_laya_dengzhi_design_user, 4, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_design_user, 5, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_design_user, 4, 0), 'rule_id': 'layadengzhi_final_tuk_nianjie',
                'calculator': partial(self.use_get_final_user_tuk_layadedngzhi,
                                      class_type=(1),
                                      d=(self.tableWidget_laya_dengzhi_design_user, 1, 0),
                                      D1=(self.tableWidget_laya_dengzhi_design_user, 2, 0),
                                      ziyou=(self.tableWidget_laya_dengzhi_design_user, 3, 0),
                                      nianjie=(self.tableWidget_laya_dengzhi_design_user, 4, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_design_user, 5, 0), ]
                                      )

            },
            # 方形
            # nd
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1_square, 3, 0), 'rule_id': 'layadengzhi_sq_nd',
                'calculator': partial(self.set_child_tb_value_nd,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 3, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 0, 0),
                                               (self.tableWidget_laya_dengzhi_cal_shouyacz, 0, 0)])
            },
            # a
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1_square, 5, 0), 'rule_id': 'layadengzhi_sq_a',
                'calculator': partial(self.set_child_tb_value_R,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 5, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0)])
            },
            # Abt
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0), 'rule_id': 'layadengzhi_sq_Abt_a',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 2, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1_square, 2, 0), 'rule_id': 'layadengzhi_sq_Abt_h0',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 2, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 4, 0)])
            },
            # Ab
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0), 'rule_id': 'layadengzhi_sq_Ab',
                'calculator': partial(self.set_child_tb_value_sq_Ab,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 1, 0)])
            },
            # A1
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0), 'rule_id': 'layadengzhi_sq_A1',
                'calculator': partial(self.set_child_tb_value_sq_A1,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 2, 0)])
            },
            # Aln
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0), 'rule_id': 'layadengzhi_sq_Aln_a',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 6, 0),
                                      source3=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 4, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1_square, 6, 0), 'rule_id': 'layadengzhi_sq_Aln_d',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 6, 0),
                                      source3=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 4, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_laya_dengzhi_cal_maogu1_square, 4, 0), 'rule_id': 'layadengzhi_sq_Aln_hn',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_laya_dengzhi_cal_maozuo1_square, 1, 0),
                                      source2=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 6, 0),
                                      source3=(self.tableWidget_laya_dengzhi_cal_maogu1_square, 4, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_cal_shouyacz, 4, 0)])
            },
            # 锚杆数
            {
                'trigger': (self.tableWidget_laya_dengzhi_design, 0, 0), 'rule_id': 'layadengzhi_maogan_count',
                'calculator': partial(self.set_maogan_count,
                                      source1=(self.tableWidget_laya_dengzhi_design, 0, 0),
                                      targets=[(self.tableWidget_laya_dengzhi_design_user, 0, 0)])
            },
            # 压力扩大
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu, 1, 0), 'rule_id': 'yalikuoda__nd',
                'calculator': partial(self.set_child_tb_value_nd,
                                      source1=(self.tableWidget_yalikuoda_cal_maogu, 1, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo, 0, 0),
                                               (self.tableWidget_yali_kuoda_cal_shouyacz, 0, 0)]
                                      )
            },
            # R
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu, 2, 0), 'rule_id': 'yalikuoda_R_div100',
                'calculator': partial(self.set_child_tb_value_R,
                                      source1=(self.tableWidget_yalikuoda_cal_maogu, 2, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo, 1, 0), ]
                                      )
            },
            # Abt
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo, 1, 0), 'rule_id': 'yalikuoda_Abt_R',
                'calculator': partial(self.set_child_tb_value_Abt,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maozuo, 2, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo, 2, 0), 'rule_id': 'yalikuoda_Abt_h0',
                'calculator': partial(self.set_child_tb_value_Abt,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maozuo, 2, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo, 4, 0), ]
                                      )
            },
            # Ab
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo, 1, 0), 'rule_id': 'yalikuoda_Ab',
                'calculator': partial(self.set_child_tb_value_Ab,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 1, 0), ]
                                      )
            },
            # A1
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo, 1, 0), 'rule_id': 'yalikuoda_A1',
                'calculator': partial(self.set_child_tb_value_A1,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 2, 0), ]
                                      )
            },
            # Aln
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu, 2, 0), 'rule_id': 'yalikuoda_Aln_R',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalikuoda_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu, 5, 0), 'rule_id': 'yalikuoda_Aln_d',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalikuoda_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu, 6, 0), 'rule_id': 'yalikuoda_Aln_hn',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalikuoda_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo, 1, 0), 'rule_id': 'yalikuoda_Aln_R_div1000',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalikuoda_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalikuoda_design_user, 1, 0), 'rule_id': 'yalikuoda_final_tuk_d',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(2),
                                      d=(self.tableWidget_yalikuoda_design_user, 1, 0),
                                      D1=(self.tableWidget_yalikuoda_design_user, 2, 0),
                                      h=(self.tableWidget_yalikuoda_design_user, 3, 0),
                                      D2=(self.tableWidget_yalikuoda_design_user, 4, 0),
                                      LD=(self.tableWidget_yalikuoda_design_user, 5, 0),
                                      targets=[(self.tableWidget_yalikuoda_design_user, 6, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_yalikuoda_design_user, 2, 0), 'rule_id': 'yalikuoda_final_tuk_D1',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(2),
                                      d=(self.tableWidget_yalikuoda_design_user, 1, 0),
                                      D1=(self.tableWidget_yalikuoda_design_user, 2, 0),
                                      h=(self.tableWidget_yalikuoda_design_user, 3, 0),
                                      D2=(self.tableWidget_yalikuoda_design_user, 4, 0),
                                      LD=(self.tableWidget_yalikuoda_design_user, 5, 0),
                                      targets=[(self.tableWidget_yalikuoda_design_user, 6, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_yalikuoda_design_user, 3, 0), 'rule_id': 'yalikuoda_final_tuk_h',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(2),
                                      d=(self.tableWidget_yalikuoda_design_user, 1, 0),
                                      D1=(self.tableWidget_yalikuoda_design_user, 2, 0),
                                      h=(self.tableWidget_yalikuoda_design_user, 3, 0),
                                      D2=(self.tableWidget_yalikuoda_design_user, 4, 0),
                                      LD=(self.tableWidget_yalikuoda_design_user, 5, 0),
                                      targets=[(self.tableWidget_yalikuoda_design_user, 6, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_yalikuoda_design_user, 4, 0), 'rule_id': 'yalikuoda_final_tuk_D2',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(2),
                                      d=(self.tableWidget_yalikuoda_design_user, 1, 0),
                                      D1=(self.tableWidget_yalikuoda_design_user, 2, 0),
                                      h=(self.tableWidget_yalikuoda_design_user, 3, 0),
                                      D2=(self.tableWidget_yalikuoda_design_user, 4, 0),
                                      LD=(self.tableWidget_yalikuoda_design_user, 5, 0),
                                      targets=[(self.tableWidget_yalikuoda_design_user, 6, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_yalikuoda_design_user, 5, 0), 'rule_id': 'yalikuoda_final_tuk_LD',
                'calculator': partial(self.use_get_final_user_tuk,
                                      class_type=(2),
                                      d=(self.tableWidget_yalikuoda_design_user, 1, 0),
                                      D1=(self.tableWidget_yalikuoda_design_user, 2, 0),
                                      h=(self.tableWidget_yalikuoda_design_user, 3, 0),
                                      D2=(self.tableWidget_yalikuoda_design_user, 4, 0),
                                      LD=(self.tableWidget_yalikuoda_design_user, 5, 0),
                                      targets=[(self.tableWidget_yalikuoda_design_user, 6, 0), ]
                                      )

            },
            # 方形
            # nd
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu_square, 3, 0), 'rule_id': 'yalikuoda_sq_nd',
                'calculator': partial(self.set_child_tb_value_nd,
                                      source1=(self.tableWidget_yalikuoda_cal_maogu_square, 3, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo_square, 0, 0),
                                               (self.tableWidget_yali_kuoda_cal_shouyacz, 0, 0)])
            },
            # a
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu_square, 5, 0), 'rule_id': 'yalikuoda_sq_a',
                'calculator': partial(self.set_child_tb_value_R,
                                      source1=(self.tableWidget_yalikuoda_cal_maogu_square, 5, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0)])
            },
            # Abt
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0), 'rule_id': 'yalikuoda_sq_Abt_a',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maozuo_square, 2, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo_square, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo_square, 2, 0), 'rule_id': 'yalikuoda_sq_Abt_h0',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maozuo_square, 2, 0),
                                      targets=[(self.tableWidget_yalikuoda_cal_maozuo_square, 4, 0)])
            },
            # Ab
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0), 'rule_id': 'yalikuoda_sq_Ab',
                'calculator': partial(self.set_child_tb_value_sq_Ab,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 1, 0)])
            },
            # A1
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0), 'rule_id': 'yalikuoda_sq_A1',
                'calculator': partial(self.set_child_tb_value_sq_A1,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 2, 0)])
            },
            # Aln
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0), 'rule_id': 'yalikuoda_sq_Aln_a',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_yalikuoda_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu_square, 6, 0), 'rule_id': 'yalikuoda_sq_Aln_d',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_yalikuoda_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_yalikuoda_cal_maogu_square, 4, 0), 'rule_id': 'yalikuoda_sq_Aln_hn',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_yalikuoda_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalikuoda_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_yalikuoda_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_yali_kuoda_cal_shouyacz, 4, 0)])
            },
            # 锚杆数
            {
                'trigger': (self.tableWidget_yalikuoda_design, 0, 0), 'rule_id': 'yalikuoda_maogan_count',
                'calculator': partial(self.set_maogan_count,
                                      source1=(self.tableWidget_yalikuoda_design, 0, 0),
                                      targets=[(self.tableWidget_yalikuoda_design_user, 0, 0)])
            },
            # 压力等值
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu, 1, 0), 'rule_id': 'yalidengzhi_nd',
                'calculator': partial(self.set_child_tb_value_nd,
                                      source1=(self.tableWidget_yalidengzhi_cal_maogu, 1, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo, 0, 0),
                                               (self.tableWidget_yali_dengzhi_cal_shouyacz, 0, 0)]
                                      )
            },
            # R
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu, 2, 0), 'rule_id': 'yalidengzhi_R_div100',
                'calculator': partial(self.set_child_tb_value_R,
                                      source1=(self.tableWidget_yalidengzhi_cal_maogu, 2, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0), ]
                                      )
            },
            # Abt
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo, 1, 0), 'rule_id': 'yalidengzhi_Abt_R',
                'calculator': partial(self.set_child_tb_value_Abt,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maozuo, 2, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo, 2, 0), 'rule_id': 'yalidengzhi_Abt_h0',
                'calculator': partial(self.set_child_tb_value_Abt,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maozuo, 2, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo, 4, 0), ]
                                      )
            },
            # Ab
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo, 1, 0), 'rule_id': 'yalidengzhi_Ab',
                'calculator': partial(self.set_child_tb_value_Ab,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 1, 0), ]
                                      )
            },
            # A1
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo, 1, 0), 'rule_id': 'yalidengzhi_A1',
                'calculator': partial(self.set_child_tb_value_A1,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 2, 0), ]
                                      )
            },
            # Aln
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu, 2, 0), 'rule_id': 'yalidengzhi_Aln_R',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalidengzhi_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu, 5, 0), 'rule_id': 'yalidengzhi_Aln_d',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalidengzhi_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu, 6, 0), 'rule_id': 'yalidengzhi_Aln_hn',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalidengzhi_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo, 1, 0), 'rule_id': 'yalidengzhi_Aln_R_div1000',
                'calculator': partial(self.set_child_tb_value_Aln,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maogu, 5, 0),
                                      source3=(self.tableWidget_yalidengzhi_cal_maogu, 6, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 4, 0), ]
                                      )
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_design_user, 1, 0), 'rule_id': 'yalidengzhi_final_tuk_d',
                'calculator': partial(self.use_get_final_user_tuk_yalidengzhi,
                                      class_type=(3),
                                      d=(self.tableWidget_yalidengzhi_design_user, 1, 0),
                                      D1=(self.tableWidget_yalidengzhi_design_user, 2, 0),
                                      LD=(self.tableWidget_yalidengzhi_design_user, 3, 0),
                                      targets=[(self.tableWidget_yalidengzhi_design_user, 4, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_yalidengzhi_design_user, 2, 0), 'rule_id': 'yalidengzhi_final_tuk_D1',
                'calculator': partial(self.use_get_final_user_tuk_yalidengzhi,
                                      class_type=(3),
                                      d=(self.tableWidget_yalidengzhi_design_user, 1, 0),
                                      D1=(self.tableWidget_yalidengzhi_design_user, 2, 0),
                                      LD=(self.tableWidget_yalidengzhi_design_user, 3, 0),
                                      targets=[(self.tableWidget_yalidengzhi_design_user, 4, 0), ]
                                      )

            },
            {
                'trigger': (self.tableWidget_yalidengzhi_design_user, 3, 0), 'rule_id': 'yalidengzhi_final_tuk_LD',
                'calculator': partial(self.use_get_final_user_tuk_yalidengzhi,
                                      class_type=(3),
                                      d=(self.tableWidget_yalidengzhi_design_user, 1, 0),
                                      D1=(self.tableWidget_yalidengzhi_design_user, 2, 0),
                                      LD=(self.tableWidget_yalidengzhi_design_user, 3, 0),
                                      targets=[(self.tableWidget_yalidengzhi_design_user, 4, 0), ]
                                      )

            },
            # 方形
            # nd
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu_square, 3, 0), 'rule_id': 'yalidengzhi_sq_nd',
                'calculator': partial(self.set_child_tb_value_nd,
                                      source1=(self.tableWidget_yalidengzhi_cal_maogu_square, 3, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo_square, 0, 0),
                                               (self.tableWidget_yali_dengzhi_cal_shouyacz, 0, 0)])
            },
            # a
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu_square, 5, 0), 'rule_id': 'yalidengzhi_sq_a',
                'calculator': partial(self.set_child_tb_value_R,
                                      source1=(self.tableWidget_yalidengzhi_cal_maogu_square, 5, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0)])
            },
            # Abt
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0), 'rule_id': 'yalidengzhi_sq_Abt_a',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maozuo_square, 2, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo_square, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo_square, 2, 0), 'rule_id': 'yalidengzhi_sq_Abt_h0',
                'calculator': partial(self.set_child_tb_value_sq_Abt,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maozuo_square, 2, 0),
                                      targets=[(self.tableWidget_yalidengzhi_cal_maozuo_square, 4, 0)])
            },
            # Ab
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0), 'rule_id': 'yalidengzhi_sq_Ab',
                'calculator': partial(self.set_child_tb_value_sq_Ab,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 1, 0)])
            },
            # A1
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0), 'rule_id': 'yalidengzhi_sq_A1',
                'calculator': partial(self.set_child_tb_value_sq_A1,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 2, 0)])
            },
            # Aln
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0), 'rule_id': 'yalidengzhi_sq_Aln_a',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_yalidengzhi_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu_square, 6, 0), 'rule_id': 'yalidengzhi_sq_Aln_d',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_yalidengzhi_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 4, 0)])
            },
            {
                'trigger': (self.tableWidget_yalidengzhi_cal_maogu_square, 4, 0), 'rule_id': 'yalidengzhi_sq_Aln_hn',
                'calculator': partial(self.set_child_tb_value_sq_Aln,
                                      source1=(self.tableWidget_yalidengzhi_cal_maozuo_square, 1, 0),
                                      source2=(self.tableWidget_yalidengzhi_cal_maogu_square, 6, 0),
                                      source3=(self.tableWidget_yalidengzhi_cal_maogu_square, 4, 0),
                                      targets=[(self.tableWidget_yali_dengzhi_cal_shouyacz, 4, 0)])
            },
            # 锚杆数
            {
                'trigger': (self.tableWidget_yalidengzhi_design, 0, 0), 'rule_id': 'yalidengzhi_maogan_count',
                'calculator': partial(self.set_maogan_count,
                                      source1=(self.tableWidget_yalidengzhi_design, 0, 0),
                                      targets=[(self.tableWidget_yalidengzhi_design_user, 0, 0)])
            },
        ]
        monitored_tables = set(rule['trigger'][0] for rule in self.calc_rules)
        for table in monitored_tables:
            table.cellChanged.connect(partial(self.on_cell_changed, table))
        # 内部计算的表格
        # 顶部4个模块按钮点击切换
        self.btns = [self.pushButton_laya_kuoda, self.pushButton_laya_dengzhi, self.pushButton_yali_kuoda,
                     self.pushButton_yali_dengzhi]
        self.img_index = 0
        # 切换的时候切换图片
        self.imgs = [
            resource_path("imgs/layakuoda.png"),
            resource_path("imgs/layadengzhi.png"),
            resource_path("imgs/yalikuoda.png"),
            resource_path("imgs/yalidengzhi.png"),
        ]
        for index, btn in enumerate(self.btns):
            btn.clicked.connect(partial(self.switch_stack_widget, index, self.imgs[index]))
        # 菜单打开文件按钮
        self.action_openfile.triggered.connect(self.open_file)
        # 菜单新建项目
        self.action_newproject.triggered.connect(self.new_project)
        # 保存
        self.action_save.triggered.connect(self.start_save_file_normal)
        self.save_type = 0
        self.action_help.triggered.connect(self.show_about_dialog)
        self.project_file_path = None  # 初始化项目文件路径
        self.project_file_json = {
            "layakuoda": {},
            "laya_dengzhi": {},
            "yali_kuoda": {},
            "yali_dengzhi": {},
        }
        self.splitter.setSizes([250, 750])  # 设置初始分割器大小比例)
        self.splitter.splitterMoved.connect(self.on_splitter_moved)
        self.splitter.hide()
        self.table_validate = NumericDelegate()
        # 所有表格设置格式验证
        tables = self.findChildren(QTableWidget)
        for tb in tables:
            tb.setItemDelegate(self.table_validate)
            header = tb.horizontalHeader()
            header.setSectionResizeMode(QHeaderView.ResizeToContents)
            # 内容变化后重新调整列宽
            tb.resizeColumnsToContents()
            set_table_height(tb)
        # 土层名称可以输入汉字
        ree_delegate = QItemDelegate()
        ree_delegate_tables = [
            self.tableWidget_laya_kuoda_soil,
            self.tableWidget_laya_dengzhi_soil,
            self.tableWidget_yalikuoda_soil,
            self.tableWidget_yalidengzhi_soil
        ]
        for tb in ree_delegate_tables:
            tb.setItemDelegateForColumn(1, ree_delegate)
        # 限制横纵限制 todo 限制输入
        valid_min_table = [
            # 拉压扩大
            {"table": self.tableWidget_laya_kuoda_base, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
                {"row": 7, "column": 0, "msg": '扩大头锚杆土厚度不宜小于5.0m'},
                {"row": 8, "column": 0, "msg": '扩大头锚杆普通段直径宜为0.2m~0.3m'},
                {"row": 9, "column": 0, "msg": '扩大头锚杆扩大段直径宜为0.4m~0.6m'},
                {"row": 10, "column": 0,
                 "msg": '宜取0.85~0.95，对强度较好的黏性土和较密实的砂性土取上限值，对强度较低的土取较小值。'},
            ]},

            {"table": self.tableWidget_laya_kuoda_base_youhua, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
                {"row": 8, "column": 0, "msg": '厚度不宜小于5.0m'},
                {"row": 9, "column": 0,
                 "msg": '宜取0.85~0.95，对强度较好的黏性土和较密实的砂性土取上限值，对强度较低的土取较小值。'},
            ]},
            # 拉压等直
            {"table": self.tableWidget_laya_dengzhi_base, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
                {"row": 7, "column": 0, "msg": '锚杆直径宜为0.2m~0.5m'},
            ]},

            {"table": self.tableWidget_laya_dengzhi_base_youhua, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
            ]},
            # 压力扩大
            {"table": self.tableWidget_yalikuoda_base, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
                {"row": 4, "column": 0, "msg": '扩大头锚杆土厚度不宜小于5.0m'},
                {"row": 5, "column": 0, "msg": '扩大头锚杆普通段直径宜为0.2m~0.3m'},
                {"row": 6, "column": 0, "msg": '扩大头锚杆扩大段直径宜为0.4m~0.6m'},
                {"row": 9, "column": 0,
                 "msg": '宜取0.85~0.95，对强度较好的黏性土和较密实的砂性土取上限值，对强度较低的土取较小值。'},
            ]},

            {"table": self.tableWidget_yalikuoda_base_youhua, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
                {"row": 5, "column": 0, "msg": '厚度不宜小于5.0m'},
                {"row": 8, "column": 0,
                 "msg": '宜取0.85~0.95，对强度较好的黏性土和较密实的砂性土取上限值，对强度较低的土取较小值。'},
            ]},
            # 压力等值
            {"table": self.tableWidget_yalidengzhi_base, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
            ]},

            {"table": self.tableWidget_yalidengzhi_base_youhua, 'tooltip': [
                {"row": 2, "column": 0, "msg": '锚杆横向间距宜为2m~4m'},
                {"row": 3, "column": 0, "msg": '锚杆纵向间距宜为2m~4m'},
            ]},

            # 拉压扩大计算
            {"table": self.tableWidget_laya_kuoda_cal_maogu, 'tooltip': [
                {"row": 0, "column": 0, "msg": '厚度不宜小于20mm'},
                {"row": 3, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {"table": self.tableWidget_laya_kuoda_cal_maogu_square, 'tooltip': [
                {"row": 0, "column": 0, "msg": '高度不宜小于20mm'},
                {"row": 1, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {
                "table": self.tableWidget_laya_kuoda_cal_maozuo, 'tooltip': [
                    {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
                ]
            },
            {
                "table": self.tableWidget_laya_kuoda_cal_maozuo_square, 'tooltip': [
                    {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
                ]
            },
            # 拉压等值计算
            {"table": self.tableWidget_laya_dengzhi_cal_maogu1, 'tooltip': [
                {"row": 0, "column": 0, "msg": '厚度不宜小于20mm'},
                {"row": 3, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {"table": self.tableWidget_laya_dengzhi_cal_maogu1_square, 'tooltip': [
                {"row": 0, "column": 0, "msg": '高度不宜小于20mm'},
                {"row": 1, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {
                "table": self.tableWidget_laya_dengzhi_cal_maozuo1, 'tooltip': [
                {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
            ]
            },
            {
                "table": self.tableWidget_laya_dengzhi_cal_maozuo1_square, 'tooltip': [
                {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
            ]
            },
            # 压力扩大计算
            {"table": self.tableWidget_yalikuoda_cal_maogu, 'tooltip': [
                {"row": 0, "column": 0, "msg": '厚度不宜小于20mm'},
                {"row": 3, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {"table": self.tableWidget_yalikuoda_cal_maogu_square, 'tooltip': [
                {"row": 0, "column": 0, "msg": '高度不宜小于20mm'},
                {"row": 1, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {
                "table": self.tableWidget_yalikuoda_cal_maozuo, 'tooltip': [
                {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
            ]
            },
            {
                "table": self.tableWidget_yalikuoda_cal_maozuo_square, 'tooltip': [
                {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
            ]
            },
            # 压力等值计算
            {"table": self.tableWidget_yalidengzhi_cal_maogu, 'tooltip': [
                {"row": 0, "column": 0, "msg": '厚度不宜小于20mm'},
                {"row": 3, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {"table": self.tableWidget_yalidengzhi_cal_maogu_square, 'tooltip': [
                {"row": 0, "column": 0, "msg": '高度不宜小于20mm'},
                {"row": 1, "column": 0, "msg": 'Q355B钢材取 295MPa,Q390 钢材取 290MPa.'},
            ]},
            {
                "table": self.tableWidget_yalidengzhi_cal_maozuo, 'tooltip': [
                {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
            ]
            },
            {
                "table": self.tableWidget_yalidengzhi_cal_maozuo_square, 'tooltip': [
                {"row": 5, "column": 0, "msg": '当截面高度≤0.8m时取1.0，当截面高度≥2.0m时取0.9，其间按线性内插取值'},
            ]
            },
        ]
        for vtb in valid_min_table:
            self.setCellNumberRange(vtb['table'], vtb['tooltip'])
        self.current_tooltip_item = None  # 跟踪当前显示tooltip的单元格
        right_btn_tb_list = [
            {'table': self.tableWidget_laya_kuoda_base, "row": 5},
            {'table': self.tableWidget_laya_kuoda_base_youhua, "row": 5},
            {'table': self.tableWidget_laya_kuoda_cal_maogu, "row": 6, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_laya_kuoda_cal_maogu_square, 'row': 4, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_laya_kuoda_cal_maozuo, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_laya_kuoda_cal_maozuo_square, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_laya_kuoda_cal_shouyacz_2, 'row': 3, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},

            {'table': self.tableWidget_laya_dengzhi_base, "row": 5},
            {'table': self.tableWidget_laya_dengzhi_base_youhua, "row": 5},
            {'table': self.tableWidget_laya_dengzhi_cal_maogu1, "row": 6, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_laya_dengzhi_cal_maogu1_square, 'row': 4, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_laya_dengzhi_cal_maozuo1, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_laya_dengzhi_cal_maozuo1_square, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_laya_dengzhi_cal_shouyacz, 'row': 3, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},

            {'table': self.tableWidget_yalikuoda_base, "row": 8},
            {'table': self.tableWidget_yalikuoda_cal_maogu, "row": 6, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_yalikuoda_cal_maogu_square, 'row': 4, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_yalikuoda_cal_maozuo, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_yalikuoda_cal_maozuo_square, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_yali_kuoda_cal_shouyacz, 'row': 3, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},

            {'table': self.tableWidget_yalidengzhi_base, "row": 5},
            {'table': self.tableWidget_yalidengzhi_base_youhua, "row": 5},
            {'table': self.tableWidget_yalidengzhi_cal_maogu, "row": 6, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_yalidengzhi_cal_maogu_square, 'row': 4, 'img_path': 'imgs/table02.png',
             'img_title': '钢筋螺纹高度取值表'},
            {'table': self.tableWidget_yalidengzhi_cal_maozuo, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_yalidengzhi_cal_maozuo_square, 'row': 6, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'},
            {'table': self.tableWidget_yali_dengzhi_cal_shouyacz, 'row': 3, 'img_path': 'imgs/table03.png',
             'img_title': '混凝土强度取值表'}
        ]
        for item in right_btn_tb_list:
            right_btn_dele = ButtonDelegate()
            item['table'].setItemDelegateForRow(item['row'], right_btn_dele)
            right_btn_dele.buttonClicked.connect(
                partial(self.cell_right_btn_click, item.get('img_path', None), item.get('img_title', '钢筋力学特性表')))
        # tab切换事件
        self.tabWidget.currentChanged.connect(self.on_tab_changed)
        self.SaveFileThread = None

        # 初始化进度对话框（全局引用防止被回收）
        self.progress_dialog = None  # 现在只在需要时才创建
        self._closing_after_save = False  # 新增标志位
        self._is_saving = False  # 保存状态标志
        # 为所有ComboBox添加事件过滤器
        comboboxs = self.findChildren(QComboBox)
        for combobox in comboboxs:
            combobox.installEventFilter(self)

        # 设置tabwidget禁用
        self.tabwidgets_list =[
            {'btn': self.pushButton_laya_kuoda_base_tuceng, "tabwidget": self.tabWidget},
            {'btn': self.pushButton_laya_dengzhi_base_tuceng, "tabwidget": self.tabWidget_layaadengzhi},
            {'btn': self.pushButton_yalikuoda_base_tuceng, "tabwidget": self.tabWidget_yalikuoda},
            {'btn': self.pushButton_yalidengzhi_base_tuceng, "tabwidget": self.tabWidget_yalidengzhi}
        ]
        for tbw in self.tabwidgets_list:
            tbw['tabwidget'].tabBar().setEnabled(False)
            tbw['btn'].clicked.connect(partial(tab_widget_switch, tbw['tabwidget'], 1))

        # 设置锚杆数量不可编辑
        self.no_edit_tables_n=[
            {"table": self.tableWidget_laya_kuoda_design_user_choice,"row":0,"col":0},
            {"table": self.tableWidget_laya_dengzhi_design_user, "row": 0, "col": 0},
            {"table": self.tableWidget_yalikuoda_design_user, "row": 0, "col": 0},
            {"table": self.tableWidget_yalidengzhi_design_user, "row": 0, "col": 0}
        ]
        # for item in self.no_edit_tables_n:
        #     set_cell_non_editable(item['table'], item['row'], item['col'])
        self.pushButton_laya_kuoda_cal_output.clicked.connect(self.laya_kuoda_cal_output_word)
        self.OutWordThread = None
        self.loading_dialog = None
        # 验算
        self.pushButton_laya_kuoda_cal_cal.clicked.connect(self.laya_kuoda_cal_cal)
        self.layakuoda_class = None
        # 拉压扩大计算按按钮点击
        self.pushButton_laya_kuoda_soil_cal.clicked.connect(self.laya_kuoda_soil_cal)
        # 去验算
        self.pushButton_laya_kuoda_design_go_cal.clicked.connect(self.laya_kuoda_go_check)
        # 拉压扩大计算返回按钮点击
        self.pushButton_laya_kuoda_soil_back.clicked.connect(partial(tab_widget_switch, self.tabWidget, 0))
        self.pushButton_laya_kuoda_design_back.clicked.connect(partial(tab_widget_switch, self.tabWidget, 1))
        self.pushButton_laya_kuoda_cal_back.clicked.connect(partial(tab_widget_switch, self.tabWidget, 2))

        # 拉压等直计算按按钮点击##########
        self.pushButton_laya_dengzhi_soil_cal.clicked.connect(self.laya_dengzhi_soil_cal)
        self.pushButton_laya_dengzhi_soil_back.clicked.connect(
            partial(tab_widget_switch, self.tabWidget_layaadengzhi, 0))
        self.pushButton_laya_dengzhi_design_back.clicked.connect(
            partial(tab_widget_switch, self.tabWidget_layaadengzhi, 1))
        self.pushButton_laya_dengzhi_cal_back.clicked.connect(
            partial(tab_widget_switch, self.tabWidget_layaadengzhi, 2))
        # 去验算
        self.pushButton_laya_dengzhidesign_go_cal.clicked.connect(self.laya_dengzhi_go_check)
        # 验算
        self.pushButton_laya_dengzhi_cal_cal.clicked.connect(self.laya_dengzhi_cal_cal)
        self.layadengzhi_class = None
        self.pushButton_laya_dengzhi_cal_output.clicked.connect(self.laya_dengzhi_cal_output_word)
        # 压力扩大#################
        self.pushButton_yalikuoda_soil_back.clicked.connect(partial(tab_widget_switch, self.tabWidget_yalikuoda, 0))
        self.pushButton_yalikuoda_design_back.clicked.connect(partial(tab_widget_switch, self.tabWidget_yalikuoda, 1))
        self.pushButton_yalikuoda_cal_back.clicked.connect(partial(tab_widget_switch, self.tabWidget_yalikuoda, 2))
        # 计算
        self.pushButton_yalikuoda_soil_cal.clicked.connect(self.yali_kuoda_soil_cal)
        self.yalikuoda_class = None
        # 去验算
        self.pushButton_yalikuoda_design_go_cal.clicked.connect(self.yali_kuoda_go_check)
        # 验算
        self.pushButton_yalikuoda_cal_cal.clicked.connect(self.yali_kuoda_cal_cal)
        self.pushButton_yalikuoda_cal_output.clicked.connect(self.yali_kuoda_cal_output_word)
        # 压力等直###################
        self.pushButton_yalidengzhi_soil_back.clicked.connect(partial(tab_widget_switch, self.tabWidget_yalidengzhi, 0))
        self.pushButton_yalidengzhi_design_back.clicked.connect(
            partial(tab_widget_switch, self.tabWidget_yalidengzhi, 1))
        self.pushButton_yalidengzhi_cal_back.clicked.connect(partial(tab_widget_switch, self.tabWidget_yalidengzhi, 2))
        self.pushButton_yalidengzhi_design_go_cal.clicked.connect(self.yali_dengzhi_go_check)
        # 计算
        self.pushButton_yalidengzhi_soil_cal.clicked.connect(self.yali_dengzhi_soil_cal)
        self.yalidengzhi_class = None
        # 验算
        self.pushButton_yalidengzhi_cal_cal.clicked.connect(self.yali_dengzhi_cal_cal)
        self.pushButton_yalidengzhi_cal_output.clicked.connect(self.yali_dengzhi_cal_output_word)

    def show_about_dialog(self):
        """显示关于对话框"""
        dialog = AboutDialog(self)
        dialog.exec_()  # 以模态方式显示对话框

    def eventFilter(self, obj, event):
        # 拦截ComboBox的滚轮事件
        if event.type() == QEvent.Wheel and isinstance(obj, QComboBox):
            return True  # 过滤掉滚轮事件
        return super().eventFilter(obj, event)

    def onComboBoxChanged(self, combobox, cb_init_text, table, table_sq, current_text):
        print(current_text)
        print(combobox)
        print(table)
        print(table_sq)
        if current_text == '优化方法':
            table_sq.show()
            table.hide()
        else:
            table_sq.hide()
            table.show()

    def onComboBoxChanged1(self, combobox, cb_init_text, table, table_sq, combobox_child, current_text):
        print(current_text)
        print(combobox)
        print(table)
        print(table_sq)
        if current_text == '正方形锚固板':
            table_sq.show()
            table.hide()
            current_index = 1
        else:
            table_sq.hide()
            table.show()
            current_index = 0
        if combobox_child:
            combobox_child.setCurrentIndex(current_index)


    def switch_stack_widget(self, index, img_path):
        """
        主界面层叠控件切换
        :param index: 索引
        :return:
        """
        self.stackedWidget.setCurrentIndex(index)
        self.display_image(img_path)
        self.img_index = index

        # 设置按钮点击样式
        for btn in self.btns:
            if btn == self.btns[index]:
                btn.setStyleSheet("""
                    background-color: #07c160;
                    border-radius: 1px;
                """)
            else:
                btn.setStyleSheet("""
                    background-color: none;
                    """)

    def open_file(self):
        print('打开文件')
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            "选择文件",
            self.folder_path,  # 默认从用户目录开始
            "项目文件 (*.json);;所有文件 (*)"
        )

        # 如果用户选择了文件，则显示文件路径
        if file_path:
            print(f"选择的文件路径: {file_path}")
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    self.read_file = json.loads(f.read())
                    self.project_file_path = file_path  # 保存项目文件路径
                    tables = self.findChildren(QTableWidget)
                    for tb in tables:
                        tb.clearContents()
                    self.splitter.show()
                    print(self.read_file)
                    try:
                        for table in self.findChildren(QTableWidget):
                            if table.objectName() in self.read_file:
                                for row_idx, row_data in enumerate(self.read_file[table.objectName()]):
                                    for col_idx, col_data in enumerate(row_data):
                                        table.setItem(row_idx, col_idx, QTableWidgetItem(str(col_data)))
                            else:
                                print(f"{table.objectName()}无数据")
                    except IndexError as e:
                        pass

                    self.pushButton_laya_kuoda.click()
                    self.layakuoda_class = None
                    self.layadengzhi_class = None
                    self.yalikuoda_class = None
                    self.yalidengzhi_class = None
            except json.JSONDecodeError:
                print("文件内容不是有效的JSON格式")
                show_error_message(self)

    def display_image(self, image_path):
        try:
            # 检查文件是否存在
            if not os.path.exists(image_path):
                self.original_pixmap = None
                return

            # 加载图片并存储原始像素版本
            self.original_pixmap = QPixmap(image_path)

            if self.original_pixmap.isNull():
                raise ValueError(f"无法加载图片: {image_path}")

            # 显示图片（自适应大小）

            if self.original_pixmap is None:
                return

            # 获取标签的大小
            label_left_img_size = self.label_left_img.size()

            # 按比例缩放图片，但保持原始像素（通过平滑缩放）
            scaled_pixmap = self.original_pixmap.scaled(
                label_left_img_size,
                Qt.KeepAspectRatio,
                Qt.SmoothTransformation  # 使用平滑变换保持像素质量
            )

            # 在标签上显示图片
            # self.widget_left_img.setStyleSheet("""
            # background-color: black;
            # """)
            self.label_left_img.setPixmap(scaled_pixmap)

        except Exception as e:
            QMessageBox.critical(self, "错误", f"显示图片时出错: {str(e)}")

    def update_image_display(self):
        if self.original_pixmap is None:
            return

        # 获取标签的大小
        label_size = self.label_left_img.size()

        # 按比例缩放图片，但保持原始像素（通过平滑缩放）
        scaled_pixmap = self.original_pixmap.scaled(
            label_size,
            Qt.KeepAspectRatio,
            Qt.SmoothTransformation  # 使用平滑变换保持像素质量
        )

        # 在标签上显示图片
        self.label_left_img.setPixmap(scaled_pixmap)

    def resizeEvent(self, event):
        # 窗口大小改变时重新调整图片显示
        self.update_image_display()
        super().resizeEvent(event)

    def on_tab_changed(self, index):
        """标签切换事件处理函数"""
        tab_name = self.tabWidget.tabText(index)
        print(f"切换到标签页: {tab_name} (索引: {index})")

    def new_project(self):
        # 创建新json文件，清空界面数据
        """选择文件夹并创建JSON文件"""
        # 1. 弹出文件夹选择对话框
        folder_path = QFileDialog.getExistingDirectory(
            self,
            "选择文件夹",
            # os.path.expanduser("~"),  # 默认从用户目录开始
            self.folder_path,
            QFileDialog.ShowDirsOnly
        )

        if not folder_path:  # 用户取消选择
            return

        try:
            # 2. 生成时间戳文件名
            timestamp = datetime.now().strftime(f"{os.getlogin()}_%Y%m%d_%H%M%S")
            filename = f"{timestamp}.json"
            file_path = os.path.join(folder_path, filename)
            self.project_file_path = file_path
            print(self.project_file_path)
            json_data = {
            }

            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(json_data, f, ensure_ascii=False, indent=4)
            tables = self.findChildren(QTableWidget)
            for tb in tables:
                tb.clearContents()
            self.splitter.show()
            self.pushButton_laya_kuoda.click()
            self.layakuoda_class = None
            self.layadengzhi_class = None
            self.yalikuoda_class = None
            self.yalidengzhi_class = None

        except Exception as e:
            QMessageBox.critical(
                self,
                "错误",
                f"项目新建失败：\n{str(e)}",
                QMessageBox.Ok
            )

    def closeEvent(self, event):
        self.save_type = 0
        if self._closing_after_save:
            event.accept()
            return
        if hasattr(self, "_is_saving") and self._is_saving:
            event.ignore()
            return
        reply = QMessageBox.question(
            self, "确认关闭", "是否保存当前项目数据?",
            QMessageBox.Cancel | QMessageBox.Save, QMessageBox.Save
        )

        if reply == QMessageBox.Save:
            self._is_saving = True
            event.ignore()  # 阻止系统关闭
            self.start_save_file()  # 启动保存
        elif reply == QMessageBox.Discard:
            event.accept()  # 不保存直接关闭
        elif reply == QMessageBox.Cancel:
            QApplication.instance().quit()
        else:  # Cancel
            event.ignore()  # 取消关闭

    def start_save_file(self, type=0):
        self.save_type = type
        if self.progress_dialog is None:
            # 在需要时才创建进度对话框
            self.progress_dialog = QProgressDialog("保存文件中...", "取消", 0, 0, self)
            self.progress_dialog.setWindowTitle("请稍候")
            self.progress_dialog.setWindowModality(Qt.WindowModal)
            self.progress_dialog.canceled.connect(self.cancel_save)  # 取消保存操作

        self.progress_dialog.show()

        # 创建新线程（避免旧线程干扰）
        self.save_thread = SaveFileThread(self.project_file_path, self.project_file_json, self)
        self.save_thread.update_signal.connect(self.on_save_complete)
        self.save_thread.start()

    def start_save_file_normal(self):
        self.start_save_file(type=1)

    def cancel_save(self):
        """用户取消保存时终止线程"""
        if hasattr(self, 'save_thread') and self.save_thread.isRunning():
            self.save_thread.terminate()  # 强制终止线程
            self.save_thread = None

            # 关闭进度对话框（如果存在）
        if self.progress_dialog:
            self.progress_dialog.close()
            self.progress_dialog = None  # 重置引用

        self._is_saving = False  # 重置保存状态

    def on_save_complete(self, res):
        if hasattr(self, 'save_thread'):
            self.save_thread.update_signal.disconnect()

        # 关闭进度对话框（如果存在）
        if self.progress_dialog:
            self.progress_dialog.close()
            self.progress_dialog = None  # 重置引用

        self._is_saving = False  # 重置保存状态
        print(res)
        if res['status'] == 1:
            self._closing_after_save = True
            QMessageBox.information(self, "成功", f"{res['message']}")
            if self.save_type == 0:
                QApplication.instance().quit()  # 直接退出应用
            else:
                self._closing_after_save = False
                print('继续使用应用')
        elif res['status'] == -1:
            QMessageBox.critical(self, "错误", f"{res['message']}")
        elif res['status'] == -2:
            QMessageBox.warning(self, "错误", f"保存文件失败:{res['message']}")
        elif res['status'] == -3:
            QMessageBox.critical(self, "错误", f"项目文件路径未设置，无法保存!")
        else:
            QMessageBox.critical(self, "错误", f"保存文件失败: {res['message']}")

    def on_splitter_moved(self):
        self.display_image(self.imgs[self.img_index])

    def laya_kuoda_soil_cal(self):
        # 土层信息
        layakuoda_soils_info = get_table_all_values(self.tableWidget_laya_kuoda_soil)
        # 土层信息
        df = pd.DataFrame(layakuoda_soils_info)
        # 天然重度
        soil_layer_gamas = [float(x) for x in df.iloc[:, 2].dropna().tolist() if x != '']
        # 粘聚力
        soil_layer_cs = [float(x) for x in df.iloc[:, 3].dropna().tolist() if x != '']
        # 内摩擦角
        soil_layer_zetas = [float(x) for x in df.iloc[:, 4].dropna().tolist() if x != '']
        # 土体与锚固粘结
        soil_layer_fmgs = [float(x) for x in df.iloc[:, 5].dropna().tolist() if x != '']
        # 厚度
        soil_layer_sizes = [float(x) for x in df.iloc[:, 6].dropna().tolist() if x != '']
        if len(soil_layer_fmgs) == 0 or len(soil_layer_sizes) == 0 or len(soil_layer_zetas) == 0 or len(
                soil_layer_cs) == 0 or len(soil_layer_gamas) == 0:
            QMessageBox.critical(
                self,
                "错误",
                "请填写土层信息",
                QMessageBox.Ok
            )
            return
        if self.comboBox_laya_kuoda_cal_method.currentText() == '传统方法':
            if not validate_table_data(self.tableWidget_laya_kuoda_base, '请完善表格信息后重试!'):
                return
            layakuoda_baseinfo = get_table_all_values(self.tableWidget_laya_kuoda_base)
            try:
                A = float(layakuoda_baseinfo[0][0])
                Pk = float(layakuoda_baseinfo[1][0])
                S1 = float(layakuoda_baseinfo[2][0])
                S2 = float(layakuoda_baseinfo[3][0])
                K = float(layakuoda_baseinfo[4][0])
                fpyk = float(layakuoda_baseinfo[5][0])
                fms = float(layakuoda_baseinfo[6][0])
                h = float(layakuoda_baseinfo[7][0])
                D1 = float(layakuoda_baseinfo[8][0]) * 1000
                D2 = float(layakuoda_baseinfo[9][0]) * 1000
                a = float(layakuoda_baseinfo[10][0])
                # zeta0 = float(layakuoda_baseinfo[11][0])
                zeta0 = 30.0

            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            # 拉压扩大
            self.layakuoda_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, fms=fms, h=h, a=a, D1=D1,
                                                D2=D2,
                                                zeta0=zeta0,
                                                soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                soil_layer_zetas=soil_layer_zetas, soil_layer_cs=soil_layer_cs,
                                                soil_layer_gamas=soil_layer_gamas, design_type=1, pwd=self.folder_path)
            self.layakuoda_class.design()
            #与ui保持一致
            n = self.layakuoda_class.n
            d = self.layakuoda_class.d
            D1 = self.layakuoda_class.D1
            h = self.layakuoda_class.h
            D2 = self.layakuoda_class.D2
            LD = self.layakuoda_class.LD
            tuk_j = self.layakuoda_class.tuk_j
            tuk_0 = np.pi * self.layakuoda_class.d * self.layakuoda_class.fms * (LD - self.layakuoda_class.delta_S)
            tuk_1 = self.layakuoda_class.fpyk * self.layakuoda_class.A_s1[1] / 1000
            tuk = min(tuk_j, tuk_0, tuk_1)
            # data = [n, h, LD, d, D1 / 1000, D2 / 1000]
            # data = [f"{n:.2f}", f"{h:.2f}", f"{LD:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{D2 / 1000:.2f}"]
            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{h:.2f}", f"{D2 / 1000:.2f}",
                        f"{math.ceil(LD * 100) / 100:.2f}", f"{tuk:.2f}"]
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            print(data)
            for row in range(self.tableWidget_laya_kuoda_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_laya_kuoda_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget, 2)
        else:
            if not validate_table_data(self.tableWidget_laya_kuoda_base_youhua, '请完善表格信息后重试!'):
                return
            layakuoda_baseinfo = get_table_all_values(self.tableWidget_laya_kuoda_base_youhua)
            try:
                A = float(layakuoda_baseinfo[0][0])
                Pk = float(layakuoda_baseinfo[1][0])
                S1 = float(layakuoda_baseinfo[2][0])
                S2 = float(layakuoda_baseinfo[3][0])
                K = float(layakuoda_baseinfo[4][0])
                fpyk = float(layakuoda_baseinfo[5][0])
                fms = float(layakuoda_baseinfo[6][0])
                h_up = float(layakuoda_baseinfo[7][0])
                h_down = float(layakuoda_baseinfo[8][0])
                a = float(layakuoda_baseinfo[9][0])
                M = float(layakuoda_baseinfo[10][0])
                N = float(layakuoda_baseinfo[11][0])
                # zeta0 = float(layakuoda_baseinfo[12][0])
                zeta0 = 30.0

            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            # 拉压扩大
            self.layakuoda_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, fms=fms, M=M, N=N, a=a,
                                                zeta0=zeta0,
                                                soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                soil_layer_zetas=soil_layer_zetas, soil_layer_cs=soil_layer_cs,
                                                soil_layer_gamas=soil_layer_gamas, design_type=1, pwd=self.folder_path)

            self.layakuoda_class.opt_space = Product(*[[180, 200, 300], [400, 500, 600], np.arange(h_down, h_up, 0.1)])
            try:
                self.layakuoda_class.optimize()
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n土层厚度不够或土层信息填写错误!\n{str(e)}",
                    QMessageBox.Ok
                )
                return
            print(self.layakuoda_class.opt_dict)
            perfect_data = self.layakuoda_class.opt_dict[min(self.layakuoda_class.opt_dict.keys())]
            n = perfect_data[4]
            d = perfect_data[3]
            LD = perfect_data[2]
            D1 = perfect_data[1]
            D2 = perfect_data[0]
            h = self.layakuoda_class.h

            n = perfect_data[0]
            d = perfect_data[1]
            D1 = perfect_data[2]
            h = perfect_data[3]
            D2 = perfect_data[4]
            LD = perfect_data[5]
            self.layakuoda_class.d = d
            self.layakuoda_class.D1 = D1
            self.layakuoda_class.D2 = D2
            self.layakuoda_class.h = h
            self.layakuoda_class.LD = LD
            tuk = perfect_data[6]

            tuk_j = perfect_data[6]
            tuk_0 = np.pi * self.layakuoda_class.d * self.layakuoda_class.fms * (LD - self.layakuoda_class.delta_S)
            tuk_1 = self.layakuoda_class.fpyk * self.layakuoda_class.A_s1[1] / 1000
            tuk = min(tuk_j, tuk_0, tuk_1)

            # data = [n, h, LD, d, D1 / 1000, D2 / 1000]
            # data = [f"{n:.2f}", f"{h:.2f}", f"{LD:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{D2 / 1000:.2f}"]
            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{h:.2f}", f"{D2 / 1000:.2f}",
                        f"{math.ceil(LD * 100) / 100:.2f}", f'{tuk:.2f}']
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            print(data)
            for row in range(self.tableWidget_laya_kuoda_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_laya_kuoda_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget, 2)
        # 同步用户选择锚杆数为计算的
        self.tableWidget_laya_kuoda_design_user_choice.setItem(0,0,QTableWidgetItem(f"{n:.2f}"))
        set_cell_non_editable(self.tableWidget_laya_kuoda_design_user_choice, 0, 0)
    def laya_kuoda_go_check(self):
        try:
            if '传统' in self.comboBox_laya_kuoda_cal_method.currentText():
                pk = float(self.tableWidget_laya_kuoda_base.item(1, 0).text())
                s1 = float(self.tableWidget_laya_kuoda_base.item(2, 0).text())
                s2 = float(self.tableWidget_laya_kuoda_base.item(3, 0).text())
            else:
                pk = float(self.tableWidget_laya_kuoda_base_youhua.item(1, 0).text())
                s1 = float(self.tableWidget_laya_kuoda_base_youhua.item(0, 0).text())
                s2 = float(self.tableWidget_laya_kuoda_base_youhua.item(0, 0).text())

            n = float(self.tableWidget_laya_kuoda_design_user_choice.item(0, 0).text())  #用户选择锚杆数
            d = float(self.tableWidget_laya_kuoda_design_user_choice.item(1, 0).text())  #用户选择钢筋公称直径
            # nwk = pk * a
            # nd = 1.05*1.3*pk*s1*s2
            nd = 1.05 * 1.3 * pk * s1 * s2
            # self.tableWidget_laya_kuoda_cal_all_stable.setItem(3, 0, QTableWidgetItem(f"{nwk:.2f}"))  # nw,k
            self.tableWidget_laya_kuoda_cal_maogu.setItem(1, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_laya_kuoda_cal_maogu_square.setItem(3, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_laya_kuoda_cal_maogu.setItem(5, 0, QTableWidgetItem(f"{d}"))  #直径
            self.tableWidget_laya_kuoda_cal_maogu_square.setItem(6, 0, QTableWidgetItem(f"{d}"))  # 直径
            self.tableWidget_laya_kuoda_cal_maozuo.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  #nd
            self.tableWidget_laya_kuoda_cal_maozuo_square.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  #nd
            self.tableWidget_laya_kuoda_cal_shouyacz_2.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  #nd
            tab_widget_switch(self.tabWidget, 3)
        except Exception as e:
            QMessageBox.critical(
                self,
                "错误",
                f"数据填写错误,请检查：\n{str(e)}",
                QMessageBox.Ok
            )
            return

    def laya_dengzhi_go_check(self):
        try:
            if '传统' in self.comboBox_laya_dengzhi_cal_method.currentText():
                pk = float(self.tableWidget_laya_dengzhi_base.item(1, 0).text())
                s1 = float(self.tableWidget_laya_dengzhi_base.item(2, 0).text())
                s2 = float(self.tableWidget_laya_dengzhi_base.item(3, 0).text())
            else:
                pk = float(self.tableWidget_laya_dengzhi_base_youhua.item(1, 0).text())
                s1 = float(self.tableWidget_laya_dengzhi_base_youhua.item(2, 0).text())
                s2 = float(self.tableWidget_laya_dengzhi_base_youhua.item(3, 0).text())

            n = float(self.tableWidget_laya_dengzhi_design_user.item(0, 0).text())
            d = float(self.tableWidget_laya_dengzhi_design_user.item(1, 0).text())
            # nwk = pk * a
            nd = 1.05 * 1.3 * pk * s1 * s2
            # self.tableWidget_laya_dengzhi_cal_all_stable.setItem(3, 0, QTableWidgetItem(f"{nwk:.2f}"))  # nw,k
            self.tableWidget_laya_dengzhi_cal_maogu1.setItem(1, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_laya_dengzhi_cal_maogu1_square.setItem(3, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_laya_dengzhi_cal_maogu1.setItem(5, 0, QTableWidgetItem(f"{d:.2f}"))  # d
            self.tableWidget_laya_dengzhi_cal_maogu1_square.setItem(6, 0, QTableWidgetItem(f"{d:.2f}"))  # d
            self.tableWidget_laya_dengzhi_cal_maozuo1.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd
            self.tableWidget_laya_dengzhi_cal_maozuo1_square.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd
            self.tableWidget_laya_dengzhi_cal_shouyacz.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd

            tab_widget_switch(self.tabWidget_layaadengzhi, 3)
        except Exception as e:
            QMessageBox.critical(
                self,
                "错误",
                f"数据填写错误,请检查：\n{str(e)}",
                QMessageBox.Ok
            )
            return

    def yali_kuoda_go_check(self):
        try:
            if '传统' in self.comboBox_yalikuoda_cal_method.currentText():
                pk = float(self.tableWidget_yalikuoda_base.item(1, 0).text())
                s1 = float(self.tableWidget_yalikuoda_base.item(2, 0).text())
                s2 = float(self.tableWidget_yalikuoda_base.item(3, 0).text())
            else:
                pk = float(self.tableWidget_yalikuoda_base_youhua.item(1, 0).text())
                s1 = float(self.tableWidget_yalikuoda_base_youhua.item(2, 0).text())
                s2 = float(self.tableWidget_yalikuoda_base_youhua.item(3, 0).text())
            n = float(self.tableWidget_yalikuoda_design_user.item(0, 0).text())
            d = float(self.tableWidget_yalikuoda_design_user.item(1, 0).text())
            # nwk = pk * a
            nd = 1.05 * 1.3 * pk * s1 * s2
            # self.tableWidget_yalikuoda_cal_all_stable_left.setItem(3, 0, QTableWidgetItem(f"{nwk:.2f}"))  # nw,k
            self.tableWidget_yalikuoda_cal_maogu.setItem(1, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_yalikuoda_cal_maogu_square.setItem(3, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_yalikuoda_cal_maogu.setItem(5, 0, QTableWidgetItem(f"{d:.2f}"))  # d
            self.tableWidget_yalikuoda_cal_maogu_square.setItem(6, 0, QTableWidgetItem(f"{d:.2f}"))  # d
            self.tableWidget_yalikuoda_cal_maozuo.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd
            self.tableWidget_yalikuoda_cal_maozuo_square.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd
            self.tableWidget_yali_kuoda_cal_shouyacz.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd
            tab_widget_switch(self.tabWidget_yalikuoda, 3)
        except Exception as e:
            QMessageBox.critical(
                self,
                "错误",
                f"数据填写错误,请检查：\n{str(e)}",
                QMessageBox.Ok
            )
            return

    def yali_dengzhi_go_check(self):
        try:
            if '传统' in self.comboBox_yalidengzhi_cal_method.currentText():
                pk = float(self.tableWidget_yalidengzhi_base.item(1, 0).text())
                s1 = float(self.tableWidget_yalidengzhi_base.item(2, 0).text())
                s2 = float(self.tableWidget_yalidengzhi_base.item(3, 0).text())
            else:
                pk = float(self.tableWidget_yalidengzhi_base_youhua.item(1, 0).text())
                s1 = float(self.tableWidget_yalidengzhi_base_youhua.item(2, 0).text())
                s2 = float(self.tableWidget_yalidengzhi_base_youhua.item(3, 0).text())

            n = float(self.tableWidget_yalidengzhi_design_user.item(0, 0).text())
            d = float(self.tableWidget_yalidengzhi_design_user.item(1, 0).text())
            # nwk = pk * a
            nd = 1.05 * 1.3 * pk * s1 * s2
            # self.tableWidget_yalidengzhi_cal_all_stable_left.setItem(3, 0, QTableWidgetItem(f"{nwk:.2f}"))  # nw,k
            self.tableWidget_yalidengzhi_cal_maogu.setItem(1, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_yalidengzhi_cal_maogu_square.setItem(3, 0, QTableWidgetItem(f"{nd:.2f}"))  # Nd
            self.tableWidget_yalidengzhi_cal_maogu.setItem(5, 0, QTableWidgetItem(f"{d:.2f}"))  # d
            self.tableWidget_yalidengzhi_cal_maogu_square.setItem(6, 0, QTableWidgetItem(f"{d:.2f}"))  # d
            self.tableWidget_yalidengzhi_cal_maozuo.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd
            self.tableWidget_yalidengzhi_cal_maozuo_square.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd
            self.tableWidget_yali_dengzhi_cal_shouyacz.setItem(0, 0, QTableWidgetItem(f"{nd:.2f}"))  # nd

            tab_widget_switch(self.tabWidget_yalidengzhi, 3)
        except Exception as e:
            QMessageBox.critical(
                self,
                "错误",
                f"数据填写错误,请检查：\n{str(e)}",
                QMessageBox.Ok
            )
            return

    def laya_kuoda_cal_cal(self):
        if self.layakuoda_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再验算。")
            return
        self.textEdit_layakuoda.clear()
        cursor = self.textEdit_layakuoda.textCursor()
        cursor.setCharFormat(QTextCharFormat())
        cursor.insertText(f'*****验算结果({formart_date()})*****\n')
        # 整体性验算
        if validate_table_data(self.tableWidget_laya_kuoda_cal_all_stable, '请完善整体稳定性表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_laya_kuoda_cal_all_stable)
            gk = float(res[0][0])
            rk = float(res[1][0])
            kw = float(res[2][0])
            nwk = float(res[3][0])
            wk = float(res[4][0])
            try:
                validate_res = self.layakuoda_class.validation_total(gk=gk, rk=rk, wk=wk, nwk=nwk, kw=kw)[-1]
                text_edit_set_text_color(self.textEdit_layakuoda, '整体稳定性验算结果:',
                                         '通过' if validate_res else "未通过", True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_layakuoda, '整体稳定性验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)
        if self.comboBox_laya_kuoda_cal_all_maogu.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_laya_kuoda_cal_maogu, '请完善圆形锚固板表格信息后重试!',
                                   is_show_box=False):
                circle = {}
                res = get_table_all_values(self.tableWidget_laya_kuoda_cal_maogu)
                # circle['type'] = 1  # 拉压扩大圆形锚固板
                circle['t'] = float(res[0][0])  # 锚固板厚度
                circle['nd'] = float(res[1][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[2][0])  # 锚固板外半径
                circle['f'] = float(res[3][0])  # 锚固板钢材抗拉强度设计值
                circle['sn'] = float(res[4][0])  # 六角螺母对边宽度
                circle['d'] = float(res[5][0])  # 钢筋直径
                circle['hn'] = float(res[6][0])  # 钢筋螺纹高度
                circle['shape'] = 'circle'
                try:
                    validate_res = self.layakuoda_class.strength_validation_circle(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚固板强度验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚固板强度验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)

        else:
            if validate_table_data(self.tableWidget_laya_kuoda_cal_maogu_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_laya_kuoda_cal_maogu_square)
                # square['type'] = 1
                square['t'] = float(res[0][0])  # 锚固板厚度t
                square['f'] = float(res[1][0])  # 锚固板钢材抗拉强度设计值
                square['sn'] = float(res[2][0])  # 六角螺母对边宽度
                square['nd'] = float(res[3][0])  # 锚杆轴向拉力设计值Nd
                square['hn'] = float(res[4][0])  # 钢筋螺纹高度
                square['a'] = float(res[5][0])  # 正方形锚固板边长
                square['d'] = float(res[6][0])  # 钢筋直径
                square['shape'] = 'square'
                try:
                    validate_res = self.layakuoda_class.strength_validation_circle(**square)[-1]
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚固板强度验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚固板强度验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        if self.comboBox_laya_kuoda_cal_all_maozuo.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_laya_kuoda_cal_maozuo, '', False):
                circle = {}
                res = get_table_all_values(self.tableWidget_laya_kuoda_cal_maozuo)
                circle['nd'] = float(res[0][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[1][0])  # R——圆形锚固板外半径（m）
                circle['h0'] = float(res[2][0])  # h0截面有效高度
                circle['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                circle['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                circle['beta_h'] = float(res[5][0])  # 截面高度影响系数
                circle['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                circle['shape'] = 'circle'
                try:
                    validate_res = self.layakuoda_class.validation_chong_qie_cheng_zai_li(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)

        else:
            if validate_table_data(self.tableWidget_laya_kuoda_cal_maozuo_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_laya_kuoda_cal_maozuo_square)
                square['nd'] = float(res[0][0])
                square['a'] = float(res[1][0])  # 正方形锚固板边长a
                square['h0'] = float(res[2][0])  # h0截面有效高度
                square['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                square['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                square['beta_h'] = float(res[5][0])  # 截面高度影响系数
                square['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                square['shape'] = 'square'
                try:
                    validate_res = self.layakuoda_class.validation_chong_qie_cheng_zai_li(**square)[-1]
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layakuoda, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        # 受压承载验算
        if validate_table_data(self.tableWidget_laya_kuoda_cal_shouyacz_2, '请完善受压承载表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_laya_kuoda_cal_shouyacz_2)
            v_d = {}
            v_d['nd'] = float(res[0][0])
            v_d['A_D'] = float(res[1][0])
            v_d['A_I'] = float(res[2][0])
            v_d['f_c'] = float(res[3][0])
            v_d['A_ln'] = float(res[4][0])
            try:
                validate_res = self.layakuoda_class.validation_shou_ya_chengzai_li(**v_d)[-1]
                text_edit_set_text_color(self.textEdit_layakuoda, '锚座节点受压承载力验算结果:',
                                         '通过' if validate_res else "未通过",
                                         True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_layakuoda, '锚座节点受压承载力验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)

    def laya_kuoda_cal_output_word(self):
        if self.layakuoda_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再操作")
            return
        self.loading_dialog = LoadingDialog(self, '正在生成计算书,请稍后...')
        self.loading_dialog.show()
        self.OutWordThread = OutWordThread(self)
        self.OutWordThread.update_signal.connect(self.on_output_word_complete)
        self.OutWordThread.start()

    def on_output_word_complete(self, res):
        if self.loading_dialog:
            self.loading_dialog.close()
            self.loading_dialog = None
        if res['status'] == 1:
            print(res['message'])
            QMessageBox.information(self, "成功", f"{res['message']}")
        else:
            QMessageBox.critical(self, "错误", f"{res['message']}")

    # 拉压等直
    def laya_dengzhi_soil_cal(self):
        # 土层信息
        laya_dengzhi_soils_info = get_table_all_values(self.tableWidget_laya_dengzhi_soil)
        # 土层信息
        df = pd.DataFrame(laya_dengzhi_soils_info)
        # 重度
        soil_layer_gamas = [float(x) for x in df.iloc[:, 2].dropna().tolist() if x != '']
        # 土体与锚固粘结
        soil_layer_fmgs = [float(x) for x in df.iloc[:, 3].dropna().tolist() if x != '']
        # 厚度
        soil_layer_sizes = [float(x) for x in df.iloc[:, 4].dropna().tolist() if x != '']
        if len(soil_layer_fmgs) == 0 or len(soil_layer_sizes) == 0 or len(soil_layer_gamas) == 0:
            QMessageBox.critical(
                self,
                "错误",
                "请填写土层信息",
                QMessageBox.Ok
            )
            return
        if self.comboBox_laya_dengzhi_cal_method.currentText() == '传统方法':
            if not validate_table_data(self.tableWidget_laya_dengzhi_base, '请完善表格信息后重试!'):
                return
            layadengzhi_baseinfo = get_table_all_values(self.tableWidget_laya_dengzhi_base)
            try:
                A = float(layadengzhi_baseinfo[0][0])
                Pk = float(layadengzhi_baseinfo[1][0])
                S1 = float(layadengzhi_baseinfo[2][0])
                S2 = float(layadengzhi_baseinfo[3][0])
                K = float(layadengzhi_baseinfo[4][0])
                fpyk = float(layadengzhi_baseinfo[5][0])
                fms = float(layadengzhi_baseinfo[6][0])

                D1 = float(layadengzhi_baseinfo[7][0]) * 1000
                # h = float(layadengzhi_baseinfo[8][0])
                # h = float(layakuoda_baseinfo[9][0])
                # a = float(layakuoda_baseinfo[10][0])
                # zeta0 = float(layakuoda_baseinfo[11][0])

            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return
            self.layadengzhi_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, fms=fms, D1=D1,
                                                  soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                  soil_layer_gamas=soil_layer_gamas, design_type=2,
                                                  pwd=self.folder_path)
            self.layadengzhi_class.design()

            n = self.layadengzhi_class.n  # 锚杆数量
            d = self.layadengzhi_class.d  # 钢筋直径
            # 锚杆直径取前面表格的 锚杆直径
            # 需要加变量# 锚杆直径
            maogan_r = D1 / 1000
            # D2 = D2
            LD = self.layadengzhi_class.LD  # 总长
            delta_S = self.layadengzhi_class.target_min_ld_without_delta_S  # #粘结段长度
            free_lenth = LD - delta_S  # 自由段长度

            tuk_j = self.layadengzhi_class.tuk_j
            tuk_0 = np.pi * self.layadengzhi_class.d * self.layadengzhi_class.fms * delta_S
            tuk_1 = self.layadengzhi_class.fpyk * self.layadengzhi_class.A_s1[1] / 1000
            tuk = min(tuk_j, tuk_0, tuk_1)

            # 调整顺序
            # data = [f"{n:.2f}", f"{h:.2f}", f"{LD:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{D2 / 1000:.2f}"]
            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{maogan_r:.2f}", f"{free_lenth:.2f}", f"{math.ceil(delta_S * 100)/100:.2f}",
                        f'{tuk:.2f}']
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            print(data)
            for row in range(self.tableWidget_laya_dengzhi_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_laya_dengzhi_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget_layaadengzhi, 2)
        else:
            if not validate_table_data(self.tableWidget_laya_dengzhi_base_youhua, '请完善表格信息后重试!'):
                return
            layakuoda_baseinfo = get_table_all_values(self.tableWidget_laya_dengzhi_base_youhua)
            try:
                A = float(layakuoda_baseinfo[0][0])
                Pk = float(layakuoda_baseinfo[1][0])
                S1 = float(layakuoda_baseinfo[2][0])
                S2 = float(layakuoda_baseinfo[3][0])
                K = float(layakuoda_baseinfo[4][0])
                fpyk = float(layakuoda_baseinfo[5][0])
                fms = float(layakuoda_baseinfo[6][0])
                # h_up = float(layakuoda_baseinfo[7][0])
                # h_down = float(layakuoda_baseinfo[8][0])
                # a = float(layakuoda_baseinfo[9][0])
                M = float(layakuoda_baseinfo[7][0])
                N = float(layakuoda_baseinfo[8][0])
                # D1 = float(layakuoda_baseinfo[9][0]) * 1000
                # zeta0 = float(layakuoda_baseinfo[12][0])
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            self.layadengzhi_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, fms=fms, M=M, N=N,
                                                  soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                  soil_layer_gamas=soil_layer_gamas, design_type=2,
                                                  pwd=self.folder_path)

            # self.layadengzhi_class.opt_space = Product(*[[180, 200, 300], [400, 500, 600]])
            # try:
            self.layadengzhi_class.optimize()
            # except Exception as e:
            #     QMessageBox.critical(
            #         self,
            #         "错误",
            #         f"数据填写错误,请检查：\n土层厚度不够或土层信息填写错误!\n{str(e)}",
            #         QMessageBox.Ok
            #     )
            #     return
            print(self.layadengzhi_class.opt_dict)
            perfect_data = self.layadengzhi_class.opt_dict[min(self.layadengzhi_class.opt_dict.keys())]
            # todo 优化缺少Δs，需要重新给值

            n = perfect_data[4]
            d = perfect_data[3]
            LD = perfect_data[2]  # 总长
            D1 = perfect_data[1]
            D2 = perfect_data[0]
            h = self.layadengzhi_class.d
            delta_S = perfect_data[-1]
            ld = LD - delta_S
            # data = [n, h, LD, d, D1 / 1000, D2 / 1000]
            n = perfect_data[0]
            d = perfect_data[1]
            D1 = perfect_data[2]
            free_len = perfect_data[3]
            connect_len = perfect_data[4]
            tuk = perfect_data[5]
            tuk_j = perfect_data[5]
            self.layadengzhi_class.d = d
            self.layadengzhi_class.n = n
            self.layadengzhi_class.D1 = D1
            self.layadengzhi_class.target_min_ld_without_delta_S = connect_len
            self.layadengzhi_class.LD = connect_len + free_len
            tuk_0 = np.pi * self.layadengzhi_class.d * self.layadengzhi_class.fms * connect_len
            tuk_1 = self.layadengzhi_class.fpyk * self.layadengzhi_class.A_s1[1] / 1000
            tuk = min(tuk_j, tuk_0, tuk_1)

            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{free_len:.2f}", f"{math.ceil(connect_len * 100) / 100:.2f}",
                        f'{tuk:.2f}']
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            print(data)
            for row in range(self.tableWidget_laya_dengzhi_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_laya_dengzhi_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget_layaadengzhi, 2)
        # 同步用户选择锚杆数为计算的
        self.tableWidget_laya_dengzhi_design_user.setItem(0,0,QTableWidgetItem(f"{n:.2f}"))
        set_cell_non_editable(self.tableWidget_laya_dengzhi_design_user, 0, 0)
    def laya_dengzhi_cal_cal(self):
        if self.layadengzhi_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再验算。")
            return
        self.textEdit_layadengzhi.clear()
        cursor = self.textEdit_layadengzhi.textCursor()
        cursor.setCharFormat(QTextCharFormat())
        cursor.insertText(f'*****验算结果({formart_date()})*****\n')
        # 整体性验算
        if validate_table_data(self.tableWidget_laya_dengzhi_cal_all_stable, '请完善整体稳定性表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_laya_dengzhi_cal_all_stable)
            gk = float(res[0][0])
            rk = float(res[1][0])
            kw = float(res[2][0])
            nwk = float(res[3][0])
            wk = float(res[4][0])
            try:
                validate_res = self.layadengzhi_class.validation_total(gk=gk, rk=rk, wk=wk, nwk=nwk, kw=kw)[-1]
                text_edit_set_text_color(self.textEdit_layadengzhi, '整体稳定性验算结果:',
                                         '通过' if validate_res else "未通过", True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_layadengzhi, '整体稳定性验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)
        if self.comboBox_laya_dengzhi_cal_all_maogu.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_laya_dengzhi_cal_maogu1, '请完善圆形锚固板表格信息后重试!',
                                   is_show_box=False):
                circle = {}
                res = get_table_all_values(self.tableWidget_laya_dengzhi_cal_maogu1)
                # circle['type'] = 1  # 拉压扩大圆形锚固板
                circle['t'] = float(res[0][0])  # 锚固板厚度
                circle['nd'] = float(res[1][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[2][0])  # 锚固板外半径
                circle['f'] = float(res[3][0])  # 锚固板钢材抗拉强度设计值
                circle['sn'] = float(res[4][0])  # 六角螺母对边宽度
                circle['d'] = float(res[5][0])  # 钢筋直径
                circle['hn'] = float(res[6][0])  # 钢筋螺纹高度
                circle['shape'] = 'circle'
                try:
                    validate_res = self.layadengzhi_class.strength_validation_circle(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚固板强度验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚固板强度验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        else:
            if validate_table_data(self.tableWidget_laya_dengzhi_cal_maogu1_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_laya_dengzhi_cal_maogu1_square)
                # square['type'] = 1
                square['t'] = float(res[0][0])  # 锚固板厚度t
                square['f'] = float(res[1][0])  # 锚固板钢材抗拉强度设计值
                square['sn'] = float(res[2][0])  # 六角螺母对边宽度
                square['nd'] = float(res[3][0])  # 锚杆轴向拉力设计值Nd
                square['hn'] = float(res[4][0])  # 钢筋螺纹高度
                square['a'] = float(res[5][0])  # 正方形锚固板边长
                square['d'] = float(res[6][0])  # 钢筋直径
                square['shape'] = 'square'
                try:
                    validate_res = self.layadengzhi_class.strength_validation_circle(**square)[-1]
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚固板强度验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚固板强度验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        # 锚座冲切
        if self.comboBox_laya_dengzhi_cal_all_maozuo.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_laya_dengzhi_cal_maozuo1, '', False):
                circle = {}
                res = get_table_all_values(self.tableWidget_laya_dengzhi_cal_maozuo1)
                circle['nd'] = float(res[0][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[1][0])  # R——圆形锚固板外半径（m）
                circle['h0'] = float(res[2][0])  # h0截面有效高度
                circle['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                circle['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                circle['beta_h'] = float(res[5][0])  # 截面高度影响系数
                circle['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                circle['shape'] = 'circle'
                try:
                    validate_res = self.layadengzhi_class.validation_chong_qie_cheng_zai_li(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        else:
            if validate_table_data(self.tableWidget_laya_dengzhi_cal_maozuo1_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_laya_dengzhi_cal_maozuo1_square)
                square['nd'] = float(res[0][0])
                square['a'] = float(res[1][0])  # 正方形锚固板边长a
                square['h0'] = float(res[2][0])  # h0截面有效高度
                square['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                square['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                square['beta_h'] = float(res[5][0])  # 截面高度影响系数
                square['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                square['shape'] = 'square'
                try:
                    validate_res = self.layadengzhi_class.validation_chong_qie_cheng_zai_li(**square)[-1]
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_layadengzhi, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        # 受压承载验算
        if validate_table_data(self.tableWidget_laya_dengzhi_cal_shouyacz, '请完善受压承载表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_laya_dengzhi_cal_shouyacz)
            v_d = {}
            v_d['nd'] = float(res[0][0])
            v_d['A_D'] = float(res[1][0])
            v_d['A_I'] = float(res[2][0])
            v_d['f_c'] = float(res[3][0])
            v_d['A_ln'] = float(res[4][0])
            try:
                validate_res = self.layadengzhi_class.validation_shou_ya_chengzai_li(**v_d)[-1]
                text_edit_set_text_color(self.textEdit_layadengzhi, '锚座节点受压承载力验算结果:',
                                         '通过' if validate_res else "未通过",
                                         True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_layadengzhi, '锚座节点受压承载力验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)

    def laya_dengzhi_cal_output_word(self):
        if self.layadengzhi_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再操作")
            return
        self.loading_dialog = LoadingDialog(self, '正在生成计算书,请稍后...')
        self.loading_dialog.show()
        self.OutWordThread = OutWordThread_layadengzhi(self)
        self.OutWordThread.update_signal.connect(self.on_output_word_complete)
        self.OutWordThread.start()

    ########压力扩大
    def yali_kuoda_soil_cal(self):
        # 土层信息
        tableWidget_yalikuoda_soil = get_table_all_values(self.tableWidget_yalikuoda_soil)
        # 土层信息
        df = pd.DataFrame(tableWidget_yalikuoda_soil)
        # 天然重度
        soil_layer_gamas = [float(x) for x in df.iloc[:, 2].dropna().tolist() if x != '']
        # 粘聚力
        soil_layer_cs = [float(x) for x in df.iloc[:, 3].dropna().tolist() if x != '']
        # 内摩擦角
        soil_layer_zetas = [float(x) for x in df.iloc[:, 4].dropna().tolist() if x != '']
        # 土体与锚固粘结
        soil_layer_fmgs = [float(x) for x in df.iloc[:, 5].dropna().tolist() if x != '']
        # 厚度
        soil_layer_sizes = [float(x) for x in df.iloc[:, 6].dropna().tolist() if x != '']
        if len(soil_layer_fmgs) == 0 or len(soil_layer_sizes) == 0 or len(soil_layer_zetas) == 0 or len(
                soil_layer_cs) == 0 or len(soil_layer_gamas) == 0:
            QMessageBox.critical(
                self,
                "错误",
                "请填写土层信息",
                QMessageBox.Ok
            )
            return
        if self.comboBox_yalikuoda_cal_method.currentText() == '传统方法':
            if not validate_table_data(self.tableWidget_yalikuoda_base, '请完善表格信息后重试!'):
                return
            yalikuoda_baseinfo = get_table_all_values(self.tableWidget_yalikuoda_base)
            try:
                A = float(yalikuoda_baseinfo[0][0])
                Pk = float(yalikuoda_baseinfo[1][0])
                S1 = float(yalikuoda_baseinfo[2][0])
                S2 = float(yalikuoda_baseinfo[3][0])
                h = float(yalikuoda_baseinfo[4][0])
                D1 = float(yalikuoda_baseinfo[5][0]) * 1000
                D2 = float(yalikuoda_baseinfo[6][0]) * 1000
                K = float(yalikuoda_baseinfo[7][0])
                fpyk = float(yalikuoda_baseinfo[8][0])
                a = float(yalikuoda_baseinfo[9][0])

            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            # 压力扩大
            self.yalikuoda_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, a=a, h=h, D1=D1,
                                                D2=D2,
                                                soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                soil_layer_zetas=soil_layer_zetas, soil_layer_cs=soil_layer_cs,
                                                soil_layer_gamas=soil_layer_gamas, design_type=3, pwd=self.folder_path)
            self.yalikuoda_class.design()
            n = self.yalikuoda_class.n
            d = self.yalikuoda_class.d
            D1 = self.yalikuoda_class.D1
            h = self.yalikuoda_class.h
            D2 = self.yalikuoda_class.D2
            LD = self.yalikuoda_class.LD
            tuk_j = self.yalikuoda_class.tuk_j
            tuk_0 = self.yalikuoda_class.fpyk * self.yalikuoda_class.A_s1[1] /1000
            tuk = min(tuk_j, tuk_0)
            # data = [n, h, LD, d, D1 / 1000, D2 / 1000]
            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{h:.2f}", f"{D2 / 1000:.2f}",
                        f"{math.ceil(LD * 100) / 100:.2f}", f'{tuk:.2f}']
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            print(data)
            for row in range(self.tableWidget_yalikuoda_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_yalikuoda_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget_yalikuoda, 2)
        else:
            if not validate_table_data(self.tableWidget_yalikuoda_base_youhua, '请完善表格信息后重试!'):
                return
            yaalikuoda_baseinfo = get_table_all_values(self.tableWidget_yalikuoda_base_youhua)
            try:
                A = float(yaalikuoda_baseinfo[0][0])
                Pk = float(yaalikuoda_baseinfo[1][0])
                S1 = float(yaalikuoda_baseinfo[2][0])
                S2 = float(yaalikuoda_baseinfo[3][0])
                h_up = float(yaalikuoda_baseinfo[4][0])
                h_down = float(yaalikuoda_baseinfo[5][0])
                K = float(yaalikuoda_baseinfo[6][0])
                fpyk = float(yaalikuoda_baseinfo[7][0])
                a = float(yaalikuoda_baseinfo[8][0])
                M = float(yaalikuoda_baseinfo[9][0])
                N = float(yaalikuoda_baseinfo[10][0])
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            # 压力扩大
            self.yalikuoda_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, M=M, N=N, a=a,
                                                soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                soil_layer_zetas=soil_layer_zetas, soil_layer_cs=soil_layer_cs,
                                                soil_layer_gamas=soil_layer_gamas, design_type=3, pwd=self.folder_path)

            self.yalikuoda_class.opt_space = Product(*[[180, 200, 300], [400, 500, 600], np.arange(h_down, h_up, 0.1)])
            try:
                self.yalikuoda_class.optimize()
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n土层厚度不够或土层信息填写错误!\n{str(e)}",
                    QMessageBox.Ok
                )
                return
            print(self.yalikuoda_class.opt_dict)
            perfect_data = self.yalikuoda_class.opt_dict[min(self.yalikuoda_class.opt_dict.keys())]
            # todo 需要确认优化的是不是这个顺序返回
            n = perfect_data[4]
            d = perfect_data[3]
            LD = perfect_data[2]
            D1 = perfect_data[1]
            D2 = perfect_data[0]
            h = self.yalikuoda_class.d
            # data = [n, h, LD, d, D1 / 1000, D2 / 1000]

            n = perfect_data[0]
            d = perfect_data[1]
            D1 = perfect_data[2]
            h = perfect_data[3]
            D2 = perfect_data[4]
            LD = perfect_data[5]
            tuk = perfect_data[6]
            self.yalikuoda_class.n = n
            self.yalikuoda_class.d = d
            self.yalikuoda_class.D1 = D1
            self.yalikuoda_class.D2 = D2
            self.yalikuoda_class.LD = LD
            self.yalikuoda_class.h = h
            tuk_j = perfect_data[6]
            tuk_0 = self.yalikuoda_class.fpyk * self.yalikuoda_class.A_s1[1] / 1000
            tuk = min(tuk_j, tuk_0)
            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{h:.2f}", f"{D2 / 1000:.2f}",
                        f"{math.ceil(LD * 100) / 100:.2f}", f'{tuk:.2f}']
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            print(data)
            for row in range(self.tableWidget_yalikuoda_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_yalikuoda_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget_yalikuoda, 2)
        # 同步用户选择锚杆数为计算的
        self.tableWidget_yalikuoda_design_user.setItem(0,0,QTableWidgetItem(f"{n:.2f}"))
        set_cell_non_editable(self.tableWidget_yalikuoda_design_user, 0, 0)


    def yali_kuoda_cal_cal(self):
        if self.yalikuoda_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再验算。")
            return
        self.textEdit_yalikuoda.clear()
        cursor = self.textEdit_yalikuoda.textCursor()
        cursor.setCharFormat(QTextCharFormat())
        cursor.insertText(f'*****验算结果({formart_date()})*****\n')
        # 整体性验算
        if validate_table_data(self.tableWidget_yalikuoda_cal_all_stable_left, '请完善整体稳定性表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_yalikuoda_cal_all_stable_left)
            gk = float(res[0][0])
            rk = float(res[1][0])
            kw = float(res[2][0])
            nwk = float(res[3][0])
            wk = float(res[4][0])
            try:
                validate_res = self.yalikuoda_class.validation_total(gk=gk, rk=rk, wk=wk, nwk=nwk, kw=kw)[-1]
                text_edit_set_text_color(self.textEdit_yalikuoda, '整体稳定性验算结果:',
                                         '通过' if validate_res else "未通过", True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_yalikuoda, '整体稳定性验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)
        if validate_table_data(self.tableWidget_yalikuoda_cal_all_stable_right,
                               msg='请完善整局部受压验算表格信息后重试!', is_show_box=False):
            res = get_table_all_values(self.tableWidget_yalikuoda_cal_all_stable_right)
            v_d = {}
            v_d['ing'] = float(res[0][0])
            v_d['apn'] = float(res[1][0])
            v_d['fck'] = float(res[2][0])
            v_d['tuk'] = self.yalikuoda_class.target_tuk
            # nwk = float(res[3][0])
            # wk = float(res[4][0])
            try:
                validate_res = self.yalikuoda_class.validation_jubu_shouya(**v_d)[-1]
                text_edit_set_text_color(self.textEdit_yalikuoda, '局部受压验算结果:',
                                         '通过' if validate_res else "未通过", True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_yalikuoda, '局部受压验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)
        if self.comboBox_yalikuoda_cal_all_maogu.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_yalikuoda_cal_maogu, '请完善圆形锚固板表格信息后重试!',
                                   is_show_box=False):
                circle = {}
                res = get_table_all_values(self.tableWidget_yalikuoda_cal_maogu)
                circle['t'] = float(res[0][0])  # 锚固板厚度
                circle['nd'] = float(res[1][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[2][0])  # 锚固板外半径
                circle['f'] = float(res[3][0])  # 锚固板钢材抗拉强度设计值
                circle['sn'] = float(res[4][0])  # 六角螺母对边宽度
                circle['d'] = float(res[5][0])  # 钢筋直径
                circle['hn'] = float(res[6][0])  # 钢筋螺纹高度
                circle['shape'] = 'circle'
                try:
                    validate_res = self.yalikuoda_class.strength_validation_circle(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚固板强度验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚固板强度验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        else:
            if validate_table_data(self.tableWidget_yalikuoda_cal_maogu_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_yalikuoda_cal_maogu_square)
                square['t'] = float(res[0][0])  # 锚固板厚度t
                square['f'] = float(res[1][0])  # 锚固板钢材抗拉强度设计值
                square['sn'] = float(res[2][0])  # 六角螺母对边宽度
                square['nd'] = float(res[3][0])  # 锚杆轴向拉力设计值Nd
                square['hn'] = float(res[4][0])  # 钢筋螺纹高度
                square['a'] = float(res[5][0])  # 正方形锚固板边长
                square['d'] = float(res[6][0])  # 钢筋直径
                square['shape'] = 'square'
                try:
                    validate_res = self.yalikuoda_class.strength_validation_circle(**square)[-1]
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚固板强度验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚固板强度验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        # 锚座冲切
        if self.comboBox_yalikuodai_cal_all_maozuo.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_yalikuoda_cal_maozuo, '', False):
                circle = {}
                res = get_table_all_values(self.tableWidget_yalikuoda_cal_maozuo)
                circle['nd'] = float(res[0][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[1][0])  # R——圆形锚固板外半径（m）
                circle['h0'] = float(res[2][0])  # h0截面有效高度
                circle['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                circle['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                circle['beta_h'] = float(res[5][0])  # 截面高度影响系数
                circle['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                circle['shape'] = 'circle'
                try:
                    validate_res = self.yalikuoda_class.validation_chong_qie_cheng_zai_li(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        else:
            if validate_table_data(self.tableWidget_yalikuoda_cal_maozuo_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_yalikuoda_cal_maozuo_square)
                square['nd'] = float(res[0][0])
                square['a'] = float(res[1][0])  # 正方形锚固板边长a
                square['h0'] = float(res[2][0])  # h0截面有效高度
                square['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                square['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                square['beta_h'] = float(res[5][0])  # 截面高度影响系数
                square['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                square['shape'] = 'square'
                try:
                    validate_res = self.yalikuoda_class.validation_chong_qie_cheng_zai_li(**square)[-1]
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalikuoda, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        # 受压承载验算
        if validate_table_data(self.tableWidget_yali_kuoda_cal_shouyacz, '请完善受压承载表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_yali_kuoda_cal_shouyacz)
            v_d = {}
            v_d['nd'] = float(res[0][0])
            v_d['A_D'] = float(res[1][0])
            v_d['A_I'] = float(res[2][0])
            v_d['f_c'] = float(res[3][0])
            v_d['A_ln'] = float(res[4][0])
            try:
                validate_res = self.yalikuoda_class.validation_shou_ya_chengzai_li(**v_d)[-1]
                text_edit_set_text_color(self.textEdit_yalikuoda, '锚座节点受压承载力验算结果:',
                                         '通过' if validate_res else "未通过",
                                         True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_yalikuoda, '锚座节点受压承载力验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)

    def yali_kuoda_cal_output_word(self):
        if self.yalikuoda_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再操作")
            return
        self.loading_dialog = LoadingDialog(self, '正在生成计算书,请稍后...')
        self.loading_dialog.show()
        self.OutWordThread = OutWordThread_yalikuoda(self)
        self.OutWordThread.update_signal.connect(self.on_output_word_complete)
        self.OutWordThread.start()

    # 压力等直
    def yali_dengzhi_soil_cal(self):
        # 土层信息
        tableWidget_yalidenz_soil = get_table_all_values(self.tableWidget_yalidengzhi_soil)
        # 土层信息
        df = pd.DataFrame(tableWidget_yalidenz_soil)
        soil_layer_gamas = [float(x) for x in df.iloc[:, 2].dropna().tolist() if x != '']
        # 土体与锚固粘结
        soil_layer_fmgs = [float(x) for x in df.iloc[:, 3].dropna().tolist() if x != '']
        # 厚度
        soil_layer_sizes = [float(x) for x in df.iloc[:, 4].dropna().tolist() if x != '']
        if len(soil_layer_fmgs) == 0 or len(soil_layer_sizes) == 0 or len(soil_layer_gamas) == 0:
            QMessageBox.critical(
                self,
                "错误",
                "请填写土层信息",
                QMessageBox.Ok
            )
            return
        if self.comboBox_yalidengzhi_cal_method.currentText() == '传统方法':
            if not validate_table_data(self.tableWidget_yalidengzhi_base, '请完善表格信息后重试!'):
                return
            yalikuoda_baseinfo = get_table_all_values(self.tableWidget_yalidengzhi_base)
            try:
                A = float(yalikuoda_baseinfo[0][0])
                Pk = float(yalikuoda_baseinfo[1][0])
                S1 = float(yalikuoda_baseinfo[2][0])
                S2 = float(yalikuoda_baseinfo[3][0])
                K = float(yalikuoda_baseinfo[4][0])
                fpyk = float(yalikuoda_baseinfo[5][0])
                D1 = float(yalikuoda_baseinfo[6][0]) * 1000

            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            self.yalidengzhi_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, D1=D1,
                                                  soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                  soil_layer_gamas=soil_layer_gamas,
                                                  design_type=4, pwd=self.folder_path)
            self.yalidengzhi_class.design()
            n = self.yalidengzhi_class.n
            d = self.yalidengzhi_class.d
            maoan_r = D1
            LD = self.yalidengzhi_class.LD  # 总厂
            # delta_S = self.yalidengzhi_class.delta_S  #粘结段长度
            # free_length = LD - delta_S  #自由段长度
            # data = [n, h, LD, d, D1 / 1000, D2 / 1000]
            tuk_j = self.yalidengzhi_class.tuk_j
            tuk_0 = self.yalidengzhi_class.fpyk * self.yalidengzhi_class.A_s1[1]
            tuk = min(tuk_j, tuk_0)
            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{maoan_r / 1000:.2f}", f"{LD:.2f}",
                        f'{tuk:.2f}']
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                )
                return

            print(data)
            for row in range(self.tableWidget_yalidengzhi_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_yalidengzhi_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget_yalidengzhi, 2)
        else:
            if not validate_table_data(self.tableWidget_yalidengzhi_base_youhua, '请完善表格信息后重试!'):
                return
            yaalikuoda_baseinfo = get_table_all_values(self.tableWidget_yalidengzhi_base_youhua)
            try:
                A = float(yaalikuoda_baseinfo[0][0])
                Pk = float(yaalikuoda_baseinfo[1][0])
                S1 = float(yaalikuoda_baseinfo[2][0])
                S2 = float(yaalikuoda_baseinfo[3][0])
                K = float(yaalikuoda_baseinfo[4][0])
                fpyk = float(yaalikuoda_baseinfo[5][0])
                M = float(yaalikuoda_baseinfo[6][0])
                N = float(yaalikuoda_baseinfo[7][0])
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n{str(e)}",
                    QMessageBox.Ok
                )
                return

            # 压力等直
            self.yalidengzhi_class = AnchorDesign(A=A, Pk=Pk, S1=S1, S2=S2, K=K, fpyk=fpyk, M=M, N=N,
                                                  soil_layer_fmgs=soil_layer_fmgs, soil_layer_sizes=soil_layer_sizes,
                                                  soil_layer_gamas=soil_layer_gamas,
                                                  design_type=4, pwd=self.folder_path)

            # self.yalidengzhi_class.opt_space = Product(*[[180, 200, 300], [400, 500, 600], np.arange(h_down, h_up, 0.1)])
            try:
                self.yalidengzhi_class.optimize()
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"数据填写错误,请检查：\n土层厚度不够或土层信息填写错误!\n{str(e)}",
                    QMessageBox.Ok
                )
                return
            print(self.yalidengzhi_class.opt_dict)
            # todo 优化缺少Δs，需要重新给值
            perfect_data = self.yalidengzhi_class.opt_dict[min(self.yalidengzhi_class.opt_dict.keys())]
            try:
                n = perfect_data[4]
            except Exception as e:
                return
            d = perfect_data[3]
            LD = perfect_data[2]
            D1 = perfect_data[1]
            D2 = perfect_data[0]
            h = self.yalidengzhi_class.d

            n = perfect_data[0]
            d = perfect_data[1]
            D1 = perfect_data[2]
            LD = perfect_data[3]
            tuk = perfect_data[4]
            tuk_j =  perfect_data[4]
            self.yalidengzhi_class.n = n
            self.yalidengzhi_class.d = d
            self.yalidengzhi_class.LD = LD
            self.yalidengzhi_class.D1 = D1
            tuk_0 = self.yalidengzhi_class.fpyk * self.yalidengzhi_class.A_s1[1]
            tuk = min(tuk_j, tuk_0)
            # data = [n, h, LD, d, D1 / 1000, D2 / 1000]
            # data = [f"{n:.2f}", f"{h:.2f}", f"{LD:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{D2 / 1000:.2f}"]
            try:
                data = [f"{n:.2f}", f"{d:.2f}", f"{D1 / 1000:.2f}", f"{LD:.2f}", f'{tuk:.2f}']
            except Exception as e:
                QMessageBox.critical(
                    self,
                    "错误",
                    f"土层厚度不够或数据填写错误,请检查：\n{str(e)}",
                )
                return

            print(data)
            for row in range(self.tableWidget_yalidengzhi_design.rowCount()):
                item = QTableWidgetItem(str(data[row]))
                self.tableWidget_yalidengzhi_design.setItem(row, 0, item)
            tab_widget_switch(self.tabWidget_yalidengzhi, 2)
        # 同步用户选择锚杆数为计算的
        self.tableWidget_yalidengzhi_design_user.setItem(0,0,QTableWidgetItem(f"{n:.2f}"))
        set_cell_non_editable(self.tableWidget_yalidengzhi_design_user, 0, 0)

    def yali_dengzhi_cal_cal(self):
        if self.yalidengzhi_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再验算。")
            return
        self.textEdit_yalidengzhi.clear()
        cursor = self.textEdit_yalidengzhi.textCursor()
        cursor.setCharFormat(QTextCharFormat())
        cursor.insertText(f'*****验算结果({formart_date()})*****\n')
        # 整体性验算
        if validate_table_data(self.tableWidget_yalidengzhi_cal_all_stable_left, '请完善整体稳定性表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_yalidengzhi_cal_all_stable_left)
            gk = float(res[0][0])
            rk = float(res[1][0])
            kw = float(res[2][0])
            nwk = float(res[3][0])
            wk = float(res[4][0])
            try:
                validate_res = self.yalidengzhi_class.validation_total(gk=gk, rk=rk, wk=wk, nwk=nwk, kw=kw)[-1]
                text_edit_set_text_color(self.textEdit_yalidengzhi, '整体稳定性验算结果:',
                                         '通过' if validate_res else "未通过", True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_yalidengzhi, '整体稳定性验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)
        if validate_table_data(self.tableWidget_yalidengzhi_cal_all_stable_right,
                               msg='请完善整局部受压验算表格信息后重试!', is_show_box=False):
            res = get_table_all_values(self.tableWidget_yalidengzhi_cal_all_stable_right)
            v_d = {}
            v_d['ing'] = float(res[0][0])
            v_d['apn'] = float(res[1][0])
            v_d['fck'] = float(res[2][0])
            v_d['tuk'] = self.yalidengzhi_class.target_tuk
            try:
                validate_res = self.yalidengzhi_class.validation_jubu_shouya(**v_d)[-1]
                text_edit_set_text_color(self.textEdit_yalidengzhi, '局部受压验算结果:',
                                         '通过' if validate_res else "未通过", True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_yalidengzhi, '局部受压验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)
        if self.comboBox_yalidengzhi_cal_all_maogu.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_yalidengzhi_cal_maogu, '请完善圆形锚固板表格信息后重试!',
                                   is_show_box=False):
                circle = {}
                res = get_table_all_values(self.tableWidget_yalidengzhi_cal_maogu)
                circle['t'] = float(res[0][0])  # 锚固板厚度
                circle['nd'] = float(res[1][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[2][0])  # 锚固板外半径
                circle['f'] = float(res[3][0])  # 锚固板钢材抗拉强度设计值
                circle['sn'] = float(res[4][0])  # 六角螺母对边宽度
                circle['d'] = float(res[5][0])  # 钢筋直径
                circle['hn'] = float(res[6][0])  # 钢筋螺纹高度
                circle['shape'] = 'circle'
                try:
                    validate_res = self.yalidengzhi_class.strength_validation_circle(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚固板强度验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚固板强度验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        else:
            if validate_table_data(self.tableWidget_yalidengzhi_cal_maogu_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_yalidengzhi_cal_maogu_square)
                square['t'] = float(res[0][0])  # 锚固板厚度t
                square['f'] = float(res[1][0])  # 锚固板钢材抗拉强度设计值
                square['sn'] = float(res[2][0])  # 六角螺母对边宽度
                square['nd'] = float(res[3][0])  # 锚杆轴向拉力设计值Nd
                square['hn'] = float(res[4][0])  # 钢筋螺纹高度
                square['a'] = float(res[5][0])  # 正方形锚固板边长
                square['d'] = float(res[6][0])  # 钢筋直径
                square['shape'] = 'square'
                try:
                    validate_res = self.yalidengzhi_class.strength_validation_circle(**square)[-1]
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚固板强度验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过", True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚固板强度验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        # 锚座冲切
        if self.comboBox_yalidengzhi_cal_all_maozuo.currentText() == '圆形锚固板':
            if validate_table_data(self.tableWidget_yalidengzhi_cal_maozuo, '', False):
                circle = {}
                res = get_table_all_values(self.tableWidget_yalidengzhi_cal_maozuo)
                circle['nd'] = float(res[0][0])  # 锚杆轴向拉力设计值Nd
                circle['R'] = float(res[1][0])  # R——圆形锚固板外半径（m）
                circle['h0'] = float(res[2][0])  # h0截面有效高度
                circle['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                circle['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                circle['beta_h'] = float(res[5][0])  # 截面高度影响系数
                circle['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                circle['shape'] = 'circle'
                try:
                    validate_res = self.yalidengzhi_class.validation_chong_qie_cheng_zai_li(**circle)[-1]
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚座节点冲切承载力验算结果(圆形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        else:
            if validate_table_data(self.tableWidget_yalidengzhi_cal_maozuo_square, '', False):
                square = {}
                res = get_table_all_values(self.tableWidget_yalidengzhi_cal_maozuo_square)
                square['nd'] = float(res[0][0])
                square['a'] = float(res[1][0])  # 正方形锚固板边长a
                square['h0'] = float(res[2][0])  # h0截面有效高度
                square['psk'] = float(res[3][0])  # Psk——作用于冲切破坏椎体底面单位面积的水浮力标准值
                square['abt'] = float(res[4][0])  # Abt——冲切破坏椎体底面线围成的底面面积（m2）
                square['beta_h'] = float(res[5][0])  # 截面高度影响系数
                square['ft'] = float(res[6][0])  # ft——混凝土轴心抗拉强度设计值（kPa）
                square['shape'] = 'square'
                try:
                    validate_res = self.yalidengzhi_class.validation_chong_qie_cheng_zai_li(**square)[-1]
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             '通过' if validate_res else "未通过",
                                             True if validate_res else False)
                except Exception as e:
                    text_edit_set_text_color(self.textEdit_yalidengzhi, '锚座节点冲切承载力验算结果(正方形锚固板):',
                                             f"未通过,请检查数据填写是否正确:{str(e)}", False)
        # 受压承载验算
        if validate_table_data(self.tableWidget_yali_dengzhi_cal_shouyacz, '请完善受压承载表格信息后重试!',
                               is_show_box=False):
            res = get_table_all_values(self.tableWidget_yali_dengzhi_cal_shouyacz)
            v_d = {}
            v_d['nd'] = float(res[0][0])
            v_d['A_D'] = float(res[1][0])
            v_d['A_I'] = float(res[2][0])
            v_d['f_c'] = float(res[3][0])
            v_d['A_ln'] = float(res[4][0])
            try:
                validate_res = self.yalidengzhi_class.validation_shou_ya_chengzai_li(**v_d)[-1]
                text_edit_set_text_color(self.textEdit_yalidengzhi, '锚座节点受压承载力验算结果:',
                                         '通过' if validate_res else "未通过",
                                         True if validate_res else False)
            except Exception as e:
                text_edit_set_text_color(self.textEdit_yalidengzhi, '锚座节点受压承载力验算结果:',
                                         f"未通过,请检查数据填写是否正确:{str(e)}", False)

    def yali_dengzhi_cal_output_word(self):
        if self.yalidengzhi_class is None:
            QMessageBox.warning(self, "警告", "请先执行计算后再操作")
            return
        self.loading_dialog = LoadingDialog(self, '正在生成计算书,请稍后...')
        self.loading_dialog.show()
        self.OutWordThread = OutWordThread_yalidengzhi(self)
        self.OutWordThread.update_signal.connect(self.on_output_word_complete)
        self.OutWordThread.start()

    def setCellNumberRange(self, table, tooltip):
        """
        为指定单元格设置数字输入范围
        """
        table.cellClicked.connect(partial(self.on_cell_clicked, table, tooltip))
        table.itemEntered.connect(partial(self.on_item_entered, table))

    def on_cell_clicked(self, table, tooltip, row, column):
        """单元格点击时显示持续的tooltip"""
        item = table.item(row, column)
        if not item:
            return
        for t in tooltip:
            if t['row'] == row and t['column'] == column:
                tooltip = t['msg']
                item.setToolTip(f"{tooltip}")
                break
        self.current_tooltip_item = (row, column)

        # 获取单元格的位置
        cell_rect = table.visualItemRect(item)
        center_x = cell_rect.center().x()  # 水平中心x坐标
        bottom_y = cell_rect.bottom()  # 底部y坐标
        # 计算tooltip显示位置（单元格右下方）
        pos = table.mapToGlobal(QPoint(center_x, bottom_y))

        # 自定义tooltip样式
        QToolTip.setFont(QFont("SimHei", 10))
        QToolTip.showText(pos, item.toolTip(), table, cell_rect, 0)  # 最后一个参数0表示不自动隐藏

    def on_item_entered(self, table, item):
        """鼠标进入单元格时，如果是当前选中的单元格则重新显示tooltip"""
        if self.current_tooltip_item:
            row, col = self.current_tooltip_item
            if item.row() == row and item.column() == col:
                cell_rect = table.visualItemRect(item)
                pos = table.mapToGlobal(cell_rect.bottomRight())
                QToolTip.showText(pos, item.toolTip(), table, cell_rect, 0)

    def cell_right_btn_click(self, img_path, title, checked, default_path='imgs/table.png'):
        # 处理图片路径
        actual_path = img_path if img_path is not None else default_path
        print(f"图片路径: {actual_path}")
        print(f"标题: {title}")  # 使用新增的title参数

        # 在对话框中使用标题参数
        dialog = ImageDialog(self)
        dialog.setWindowTitle(title)  # 假设对话框有设置标题的方法
        dialog.set_image(resource_path(str(actual_path)))
        dialog.exec_()

    def on_cell_changed(self, table, row, col):
        """单元格变化触发计算"""
        # 查找所有与当前单元格匹配的规则
        matching_rules = [
            rule for rule in self.calc_rules
            if rule['trigger'][0] == table  # 同一表格
               and rule['trigger'][1] == row  # 同一行
               and rule['trigger'][2] == col  # 同一列
        ]

        # 依次执行所有匹配的规则
        for rule in matching_rules:
            print(f"执行规则: {rule['rule_id']}")  # 调试用
            rule['calculator']()

    # ------------------------------
    # 通用数据访问方法
    # ------------------------------
    def get_cell_value(self, table, row, col):
        """获取单元格值"""
        if 0 <= row < table.rowCount() and 0 <= col < table.columnCount():
            item = table.item(row, col)
            return item.text() if item else ""
        return ""

    def set_cell_value(self, table, row, col, value):
        """设置单个单元格值"""
        if 0 <= row < table.rowCount() and 0 <= col < table.columnCount():
            item = table.item(row, col) or QTableWidgetItem()
            # table.blockSignals(True)
            item.setText(str(value))
            table.setItem(row, col, item)
            # table.blockSignals(False)

    def set_multi_cell_value(self, targets, value):
        """批量设置多个单元格值"""
        for target in targets:
            table, row, col = target
            self.set_cell_value(table, row, col, value)

    def set_child_tb_value_nd(self,source1,targets):
        val1 = self.get_cell_value(*source1)

        try:
            result = float(val1)
            self.set_multi_cell_value(targets, f"{result:.2f}")  # 多目标赋值
        except Exception as e:
            print(str(e))

    def set_child_tb_value_R(self,source1,targets):
        val1 = self.get_cell_value(*source1)

        try:
            result = float(val1)
            self.set_multi_cell_value(targets, f"{result/1000:.2f}")  # 多目标赋值
        except Exception as e:
            print(str(e))

    def set_child_tb_value_Abt(self,source1,source2,targets):
        val1 = self.get_cell_value(*source1)
        val2 = self.get_cell_value(*source2)
        try:
            result =np.pi * (float(val1) + float(val2))**2
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))
    def set_child_tb_value_Ab(self,source1,targets):
        val1 = self.get_cell_value(*source1)
        print(1)
        try:
            result =np.pi * (6*float(val1))**2 / 4
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))

    def set_child_tb_value_A1(self,source1,targets):
        val1 = self.get_cell_value(*source1)
        try:
            result =np.pi * float(val1)**2
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))
    def set_child_tb_value_Aln(self,source1,source2,source3,targets):
        R = self.get_cell_value(*source1)
        d = self.get_cell_value(*source2)
        hn = self.get_cell_value(*source3)
        try:
            r = (0.5*float(d)+float(hn)+0.75)/1000
            result =(np.pi * float(R)**2) - (np.pi*r**2)
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))


    def set_child_tb_value_sq_Abt(self,source1,source2,targets):
        val1 = self.get_cell_value(*source1)
        val2 = self.get_cell_value(*source2)
        try:
            result =(float(val1)/2+float(val2))**2
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))


    def set_child_tb_value_sq_Ab(self,source1,targets):
        val1 = self.get_cell_value(*source1)
        try:
            result =(3*float(val1))**2
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))

    def set_child_tb_value_sq_A1(self,source1,targets):
        val1 = self.get_cell_value(*source1)
        try:
            result =float(val1)**2
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))

    def set_child_tb_value_sq_Aln(self,source1,source2,source3,targets):
        a = self.get_cell_value(*source1)
        d = self.get_cell_value(*source2)
        hn = self.get_cell_value(*source3)
        try:
            r = (0.5*float(d)+float(hn)+0.75)/1000
            result =(float(a)**2) - (np.pi*r**2)
            self.set_multi_cell_value(targets, f"{result:.2f}")
        except Exception as e:
                print(str(e))

    def set_maogan_count(self, source1, targets):
        val1 = self.get_cell_value(*source1)
        try:
            result = float(val1)
            self.set_multi_cell_value(targets, f"{result}")
        except Exception as e:
            print(str(e))
    def use_get_final_user_tuk(self,class_type,d,D1, h, D2, LD,targets):
        global design_class
        try:
            if class_type == 0:
                design_class = self.layakuoda_class
            elif class_type == 1:
                design_class = self.layadengzhi_class
            elif class_type == 2:
                design_class = self.yalikuoda_class
            elif class_type == 3:
                design_class = self.yalidengzhi_class
            d = float(self.get_cell_value(*d))
            D1 = float(self.get_cell_value(*D1))
            h = float(self.get_cell_value(*h))
            D2 = float(self.get_cell_value(*D2))
            LD = float(self.get_cell_value(*LD))
            print(class_type, d, D1, h, D2, LD)
            res = self.get_final_user_tuk(design_class, d, D1, h, D2, LD)
            self.set_multi_cell_value(targets, f"{float(res):.2f}")
        except Exception as e:
            print(str(e))
    def use_get_final_user_tuk_layadedngzhi(self,class_type,d,D1, ziyou, nianjie,targets):
        global design_class
        try:
            if class_type == 0:
                design_class = self.layakuoda_class
            elif class_type == 1:
                design_class = self.layadengzhi_class
            elif class_type == 2:
                design_class = self.yalikuoda_class
            elif class_type == 3:
                design_class = self.yalidengzhi_class
            d = float(self.get_cell_value(*d))
            D1 = float(self.get_cell_value(*D1))
            ziyou = float(self.get_cell_value(*ziyou))
            nianjie = float(self.get_cell_value(*nianjie))
            LD = ziyou+nianjie
            print(class_type, d, D1,ziyou, nianjie, LD)
            res = self.get_final_user_tuk(design_class, d, D1, None, None, LD, nianjie)
            self.set_multi_cell_value(targets, f"{float(res):.2f}")
        except Exception as e:
            print(str(e))
    def use_get_final_user_tuk_yalidengzhi(self,class_type,d,D1,LD,targets):
        global design_class
        try:
            if class_type == 0:
                design_class = self.layakuoda_class
            elif class_type == 1:
                design_class = self.layadengzhi_class
            elif class_type == 2:
                design_class = self.yalikuoda_class
            elif class_type == 3:
                design_class = self.yalidengzhi_class
            d = float(self.get_cell_value(*d))
            D1 = float(self.get_cell_value(*D1))
            LD = float(self.get_cell_value(*LD))
            print(class_type, d, D1,None,None, LD)
            res = self.get_final_user_tuk(design_class, d, D1, None, None, LD)
            self.set_multi_cell_value(targets, f"{float(res):.2f}")
        except Exception as e:
            print(str(e))
    def get_final_user_tuk(self, design_class: AnchorDesign, d=None, D1=None, h=None, D2=None, LD=None, target_min_ld_without_delta_S=None):
        import copy
        copy_obj = copy.deepcopy(design_class)

        for name, var in zip(["d", "D1", "h", "D2", "LD", "target_min_ld_without_delta_S"], [d, D1, h, D2, LD, target_min_ld_without_delta_S]):
            if var:
                setattr(copy_obj, name, var)
        copy_obj.D1 = copy_obj.D1 * 1000
        copy_obj.D2 = copy_obj.D2 * 1000
        if copy_obj.type in [1, 3]:
            copy_obj.init_split_index, copy_obj.sub_size_0, copy_obj.sub_size_1 = copy_obj.split_layer(copy_obj.h, copy_obj.sizes)
            copy_obj.sub_fmgs_0 = copy_obj.fmgs[: copy_obj.init_split_index + 1]
            copy_obj.sub_fgms_1 = copy_obj.fmgs[copy_obj.init_split_index:]
            copy_obj.zeta = copy_obj.zetas[copy_obj.init_split_index]
            copy_obj.gama = copy_obj.gamas[copy_obj.init_split_index]
            copy_obj.c = copy_obj.cs[copy_obj.init_split_index]
        if copy_obj.type == 1:
            tuk_0 = np.pi * copy_obj.d * copy_obj.fms * (LD - copy_obj.delta_S)
        else:
            tuk_0 = np.pi * copy_obj.d * copy_obj.fms * copy_obj.target_min_ld_without_delta_S

        public_ds = [
            25, 32, 36, 40, 50, 75
        ]
        public_across_area = [491, 804, 1018, 1257, 1963, 4418
                              ]
        As1 = public_across_area[public_ds.index(copy_obj.d)]
        tuk_1 = copy_obj.fpyk * As1 / 1000
        copy_obj.general()
        copy_obj.LD = LD
        copy_obj.d = d
        if h:
            copy_obj.h = h
        tuk_j = copy_obj.cal_total_tuk()
        self.copy_obj = copy_obj
        if not copy_obj.type in [1, 2]:
            return min(tuk_1, tuk_j)
        else:
            return min(tuk_0, tuk_1, tuk_j)

        pass